aboutsummaryrefslogtreecommitdiff
path: root/resources/assets/javascripts/lib/parse_options.js
blob: 994feb80fc9ff03a6ea590a05b7dd2318900cd13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
 * Parses a given string "foo needle[option1;option2=value;option3=42;option4=false] bar"
 * into the following structure:
 *
 * {option1: true, option2: "value", option3: 42, option4: false}
 */
function parseOptions(string, needle) {
    var temp = needle ? string.match(/\w+\[(.*?)\]/g) || [] : [string],
        options = {};

    temp.forEach(function(slice) {
        if (needle && (slice.indexOf(needle) !== 0 || slice === needle)) {
            return;
        }
        var split = needle ? slice.replace(/^\w+\[(.*)\]$/, '$1') : slice,
            index = '',
            value = '',
            inval = false,
            escaped = 0,
            inquotes = false,
            l = split.length,
            token,
            write,
            skip,
            i;
        for (i = 0; i < l; i += 1) {
            token = split[i];
            write = false;
            skip = false;
            if (inval && token === '\\' && escaped <= 0) {
                escaped = 2;
            } else if (!inval && token === '=') {
                inval = true;
                skip = true;
            } else if (inval && value.length === 0 && (token === '"' || token === "'")) {
                inquotes = token;
            } else if (inval && inquotes && escaped <= 0 && token === inquotes) {
                inquotes = false;
            } else if (!inquotes && token === ';') {
                write = true;
                skip = true;
            }
            if (!skip && escaped <= 0) {
                if (inval) {
                    value += token;
                } else {
                    index += token;
                }
            }
            escaped -= 1;

            if (write || i === split.length - 1) {
                if (i === split.length - 1 && inquotes) {
                    throw 'Invalid data, missing closing quote';
                }
                if (index.trim().length > 0) {
                    options[index.trim()] = inval ? parseValue(value) : true;
                }
                inval = false;
                inquotes = false;
                index = '';
                value = '';
            }
        }
    });
    return options;
}

/**
 * Tries to parse a given string into it's appropriate type.
 * Supports boolean, int and float.
 */
function parseValue(value) {
    if (value.toLowerCase() === 'true') {
        return true;
    }
    if (value.toLowerCase() === 'false') {
        return false;
    }
    if (/^[+-]\d+$/.test(value)) {
        return parseInt(value, 10);
    }
    if (/^[+-]\d+\.\d+$/.test(value)) {
        return parseFloat(value, 10);
    }
    return value.replace(/^(["'])(.*)\1$/, '$2');
}

export default parseOptions;