mirror of https://github.com/rancher/ui.git
192 lines
4.9 KiB
JavaScript
192 lines
4.9 KiB
JavaScript
/**
|
|
* Sanitize a JSON-like string containing. For example changes JavaScript
|
|
* notation into JSON notation.
|
|
* This function for example changes a string like "{a: 2, 'b': {c: 'd'}"
|
|
* into '{"a": 2, "b": {"c": "d"}'
|
|
* @param {string} jsString
|
|
* @returns {string} json
|
|
*/
|
|
|
|
(function () {
|
|
function generateModule(name, values) {
|
|
define(name, [], function () {
|
|
'use strict';
|
|
return values;
|
|
});
|
|
}
|
|
generateModule('json-sanitizer', {
|
|
'default': function sanitize(jsString) {
|
|
// escape all single and double quotes inside strings
|
|
var chars = [];
|
|
var i = 0;
|
|
|
|
//If JSON starts with a function (characters/digits/"_-"), remove this function.
|
|
//This is useful for "stripping" JSONP objects to become JSON
|
|
//For example: /* some comment */ function_12321321 ( [{"a":"b"}] ); => [{"a":"b"}]
|
|
var match = jsString.match(/^\s*(\/\*(.|[\r\n])*?\*\/)?\s*[\da-zA-Z_$]+\s*\(([\s\S]*)\)\s*;?\s*$/);
|
|
if (match) {
|
|
jsString = match[3];
|
|
}
|
|
|
|
// helper functions to get the current/prev/next character
|
|
function curr() { return jsString.charAt(i); }
|
|
function next() { return jsString.charAt(i + 1); }
|
|
function prev() { return jsString.charAt(i - 1); }
|
|
|
|
// get the last parsed non-whitespace character
|
|
function lastNonWhitespace() {
|
|
var p = chars.length - 1;
|
|
|
|
while (p >= 0) {
|
|
var pp = chars[p];
|
|
if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace
|
|
return pp;
|
|
}
|
|
p--;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
// skip a block comment '/* ... */'
|
|
function skipBlockComment() {
|
|
i += 2;
|
|
while (i < jsString.length && (curr() !== '*' || next() !== '/')) {
|
|
i++;
|
|
}
|
|
i += 2;
|
|
}
|
|
|
|
// skip a comment '// ...'
|
|
function skipComment() {
|
|
i += 2;
|
|
while (i < jsString.length && (curr() !== '\n')) {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// parse single or double quoted string
|
|
function parseString(quote) {
|
|
chars.push('"');
|
|
i++;
|
|
var c = curr();
|
|
while (i < jsString.length && c !== quote) {
|
|
if (c === '"' && prev() !== '\\') {
|
|
// unescaped double quote, escape it
|
|
chars.push('\\');
|
|
}
|
|
|
|
// handle escape character
|
|
if (c === '\\') {
|
|
i++;
|
|
c = curr();
|
|
|
|
// remove the escape character when followed by a single quote ', not needed
|
|
if (c !== '\'') {
|
|
chars.push('\\');
|
|
}
|
|
}
|
|
chars.push(c);
|
|
|
|
i++;
|
|
c = curr();
|
|
}
|
|
if (c === quote) {
|
|
chars.push('"');
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// parse an unquoted key
|
|
function parseKey() {
|
|
var specialValues = ['null', 'true', 'false'];
|
|
var key = '';
|
|
var c = curr();
|
|
|
|
var regexp = /[a-zA-Z_$\d]/; // letter, number, underscore, dollar character
|
|
while (regexp.test(c)) {
|
|
key += c;
|
|
i++;
|
|
c = curr();
|
|
}
|
|
|
|
if (specialValues.indexOf(key) === -1) {
|
|
chars.push('"' + key + '"');
|
|
}
|
|
else {
|
|
chars.push(key);
|
|
}
|
|
}
|
|
|
|
// parse an unquoted value
|
|
function parseValue() {
|
|
var specialValues = ['null', 'true', 'false'];
|
|
var key = '';
|
|
var c = curr();
|
|
|
|
while (i < jsString.length && [',', '}', ']'].indexOf(c) === -1) {
|
|
key += c;
|
|
i++;
|
|
c = curr();
|
|
}
|
|
|
|
key = key.trim()
|
|
|
|
if (specialValues.indexOf(key) === -1 && !(key + '').match(/^([0-9]+\.)?[0-9]*$/)) {
|
|
chars.push('"' + key + '"');
|
|
}
|
|
else {
|
|
chars.push(key);
|
|
}
|
|
}
|
|
|
|
function isTrailingComma() {
|
|
var idx = i+1;
|
|
var c = jsString.charAt(idx);
|
|
|
|
while ( idx < jsString.length && [' ','\n','\r','\t'].indexOf(c) >= 0) {
|
|
idx++;
|
|
c = jsString.charAt(idx);
|
|
}
|
|
|
|
if ( ['}',']'].indexOf(c) >= 0 ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
while (i < jsString.length) {
|
|
var c = curr();
|
|
|
|
if (c === '/' && next() === '*') {
|
|
skipBlockComment();
|
|
}
|
|
else if (c === '/' && next() === '/') {
|
|
skipComment();
|
|
}
|
|
else if (c === '\'' || c === '"') {
|
|
parseString(c);
|
|
}
|
|
else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) {
|
|
// an unquoted object key (like a in '{a:2}')
|
|
parseKey();
|
|
}
|
|
else if (c.trim() !== '' && ['[', '{'].indexOf(c) === -1 && ':' === lastNonWhitespace()) {
|
|
// an unquoted object value (like b in '{a:b}')
|
|
parseValue();
|
|
}
|
|
else if ( c === ',' && isTrailingComma() ) {
|
|
i++;
|
|
}
|
|
else {
|
|
chars.push(c);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return chars.join('');
|
|
}
|
|
});
|
|
})();
|