| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 | (function (factory) {    if (typeof module === "object" && typeof module.exports === "object") {        var v = factory(require, exports);        if (v !== undefined) module.exports = v;    }    else if (typeof define === "function" && define.amd) {        define(["require", "exports", "./scanner"], factory);    }})(function (require, exports) {    /*---------------------------------------------------------------------------------------------     *  Copyright (c) Microsoft Corporation. All rights reserved.     *  Licensed under the MIT License. See License.txt in the project root for license information.     *--------------------------------------------------------------------------------------------*/    'use strict';    Object.defineProperty(exports, "__esModule", { value: true });    exports.getNodeType = exports.stripComments = exports.visit = exports.findNodeAtOffset = exports.contains = exports.getNodeValue = exports.getNodePath = exports.findNodeAtLocation = exports.parseTree = exports.parse = exports.getLocation = void 0;    var scanner_1 = require("./scanner");    var ParseOptions;    (function (ParseOptions) {        ParseOptions.DEFAULT = {            allowTrailingComma: false        };    })(ParseOptions || (ParseOptions = {}));    /**     * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.     */    function getLocation(text, position) {        var segments = []; // strings or numbers        var earlyReturnException = new Object();        var previousNode = undefined;        var previousNodeInst = {            value: {},            offset: 0,            length: 0,            type: 'object',            parent: undefined        };        var isAtPropertyKey = false;        function setPreviousNode(value, offset, length, type) {            previousNodeInst.value = value;            previousNodeInst.offset = offset;            previousNodeInst.length = length;            previousNodeInst.type = type;            previousNodeInst.colonOffset = undefined;            previousNode = previousNodeInst;        }        try {            visit(text, {                onObjectBegin: function (offset, length) {                    if (position <= offset) {                        throw earlyReturnException;                    }                    previousNode = undefined;                    isAtPropertyKey = position > offset;                    segments.push(''); // push a placeholder (will be replaced)                },                onObjectProperty: function (name, offset, length) {                    if (position < offset) {                        throw earlyReturnException;                    }                    setPreviousNode(name, offset, length, 'property');                    segments[segments.length - 1] = name;                    if (position <= offset + length) {                        throw earlyReturnException;                    }                },                onObjectEnd: function (offset, length) {                    if (position <= offset) {                        throw earlyReturnException;                    }                    previousNode = undefined;                    segments.pop();                },                onArrayBegin: function (offset, length) {                    if (position <= offset) {                        throw earlyReturnException;                    }                    previousNode = undefined;                    segments.push(0);                },                onArrayEnd: function (offset, length) {                    if (position <= offset) {                        throw earlyReturnException;                    }                    previousNode = undefined;                    segments.pop();                },                onLiteralValue: function (value, offset, length) {                    if (position < offset) {                        throw earlyReturnException;                    }                    setPreviousNode(value, offset, length, getNodeType(value));                    if (position <= offset + length) {                        throw earlyReturnException;                    }                },                onSeparator: function (sep, offset, length) {                    if (position <= offset) {                        throw earlyReturnException;                    }                    if (sep === ':' && previousNode && previousNode.type === 'property') {                        previousNode.colonOffset = offset;                        isAtPropertyKey = false;                        previousNode = undefined;                    }                    else if (sep === ',') {                        var last = segments[segments.length - 1];                        if (typeof last === 'number') {                            segments[segments.length - 1] = last + 1;                        }                        else {                            isAtPropertyKey = true;                            segments[segments.length - 1] = '';                        }                        previousNode = undefined;                    }                }            });        }        catch (e) {            if (e !== earlyReturnException) {                throw e;            }        }        return {            path: segments,            previousNode: previousNode,            isAtPropertyKey: isAtPropertyKey,            matches: function (pattern) {                var k = 0;                for (var i = 0; k < pattern.length && i < segments.length; i++) {                    if (pattern[k] === segments[i] || pattern[k] === '*') {                        k++;                    }                    else if (pattern[k] !== '**') {                        return false;                    }                }                return k === pattern.length;            }        };    }    exports.getLocation = getLocation;    /**     * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.     * Therefore always check the errors list to find out if the input was valid.     */    function parse(text, errors, options) {        if (errors === void 0) { errors = []; }        if (options === void 0) { options = ParseOptions.DEFAULT; }        var currentProperty = null;        var currentParent = [];        var previousParents = [];        function onValue(value) {            if (Array.isArray(currentParent)) {                currentParent.push(value);            }            else if (currentProperty !== null) {                currentParent[currentProperty] = value;            }        }        var visitor = {            onObjectBegin: function () {                var object = {};                onValue(object);                previousParents.push(currentParent);                currentParent = object;                currentProperty = null;            },            onObjectProperty: function (name) {                currentProperty = name;            },            onObjectEnd: function () {                currentParent = previousParents.pop();            },            onArrayBegin: function () {                var array = [];                onValue(array);                previousParents.push(currentParent);                currentParent = array;                currentProperty = null;            },            onArrayEnd: function () {                currentParent = previousParents.pop();            },            onLiteralValue: onValue,            onError: function (error, offset, length) {                errors.push({ error: error, offset: offset, length: length });            }        };        visit(text, visitor, options);        return currentParent[0];    }    exports.parse = parse;    /**     * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.     */    function parseTree(text, errors, options) {        if (errors === void 0) { errors = []; }        if (options === void 0) { options = ParseOptions.DEFAULT; }        var currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root        function ensurePropertyComplete(endOffset) {            if (currentParent.type === 'property') {                currentParent.length = endOffset - currentParent.offset;                currentParent = currentParent.parent;            }        }        function onValue(valueNode) {            currentParent.children.push(valueNode);            return valueNode;        }        var visitor = {            onObjectBegin: function (offset) {                currentParent = onValue({ type: 'object', offset: offset, length: -1, parent: currentParent, children: [] });            },            onObjectProperty: function (name, offset, length) {                currentParent = onValue({ type: 'property', offset: offset, length: -1, parent: currentParent, children: [] });                currentParent.children.push({ type: 'string', value: name, offset: offset, length: length, parent: currentParent });            },            onObjectEnd: function (offset, length) {                ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete                currentParent.length = offset + length - currentParent.offset;                currentParent = currentParent.parent;                ensurePropertyComplete(offset + length);            },            onArrayBegin: function (offset, length) {                currentParent = onValue({ type: 'array', offset: offset, length: -1, parent: currentParent, children: [] });            },            onArrayEnd: function (offset, length) {                currentParent.length = offset + length - currentParent.offset;                currentParent = currentParent.parent;                ensurePropertyComplete(offset + length);            },            onLiteralValue: function (value, offset, length) {                onValue({ type: getNodeType(value), offset: offset, length: length, parent: currentParent, value: value });                ensurePropertyComplete(offset + length);            },            onSeparator: function (sep, offset, length) {                if (currentParent.type === 'property') {                    if (sep === ':') {                        currentParent.colonOffset = offset;                    }                    else if (sep === ',') {                        ensurePropertyComplete(offset);                    }                }            },            onError: function (error, offset, length) {                errors.push({ error: error, offset: offset, length: length });            }        };        visit(text, visitor, options);        var result = currentParent.children[0];        if (result) {            delete result.parent;        }        return result;    }    exports.parseTree = parseTree;    /**     * Finds the node at the given path in a JSON DOM.     */    function findNodeAtLocation(root, path) {        if (!root) {            return undefined;        }        var node = root;        for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {            var segment = path_1[_i];            if (typeof segment === 'string') {                if (node.type !== 'object' || !Array.isArray(node.children)) {                    return undefined;                }                var found = false;                for (var _a = 0, _b = node.children; _a < _b.length; _a++) {                    var propertyNode = _b[_a];                    if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment) {                        node = propertyNode.children[1];                        found = true;                        break;                    }                }                if (!found) {                    return undefined;                }            }            else {                var index = segment;                if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {                    return undefined;                }                node = node.children[index];            }        }        return node;    }    exports.findNodeAtLocation = findNodeAtLocation;    /**     * Gets the JSON path of the given JSON DOM node     */    function getNodePath(node) {        if (!node.parent || !node.parent.children) {            return [];        }        var path = getNodePath(node.parent);        if (node.parent.type === 'property') {            var key = node.parent.children[0].value;            path.push(key);        }        else if (node.parent.type === 'array') {            var index = node.parent.children.indexOf(node);            if (index !== -1) {                path.push(index);            }        }        return path;    }    exports.getNodePath = getNodePath;    /**     * Evaluates the JavaScript object of the given JSON DOM node     */    function getNodeValue(node) {        switch (node.type) {            case 'array':                return node.children.map(getNodeValue);            case 'object':                var obj = Object.create(null);                for (var _i = 0, _a = node.children; _i < _a.length; _i++) {                    var prop = _a[_i];                    var valueNode = prop.children[1];                    if (valueNode) {                        obj[prop.children[0].value] = getNodeValue(valueNode);                    }                }                return obj;            case 'null':            case 'string':            case 'number':            case 'boolean':                return node.value;            default:                return undefined;        }    }    exports.getNodeValue = getNodeValue;    function contains(node, offset, includeRightBound) {        if (includeRightBound === void 0) { includeRightBound = false; }        return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));    }    exports.contains = contains;    /**     * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.     */    function findNodeAtOffset(node, offset, includeRightBound) {        if (includeRightBound === void 0) { includeRightBound = false; }        if (contains(node, offset, includeRightBound)) {            var children = node.children;            if (Array.isArray(children)) {                for (var i = 0; i < children.length && children[i].offset <= offset; i++) {                    var item = findNodeAtOffset(children[i], offset, includeRightBound);                    if (item) {                        return item;                    }                }            }            return node;        }        return undefined;    }    exports.findNodeAtOffset = findNodeAtOffset;    /**     * Parses the given text and invokes the visitor functions for each object, array and literal reached.     */    function visit(text, visitor, options) {        if (options === void 0) { options = ParseOptions.DEFAULT; }        var _scanner = scanner_1.createScanner(text, false);        function toNoArgVisit(visitFunction) {            return visitFunction ? function () { return visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };        }        function toOneArgVisit(visitFunction) {            return visitFunction ? function (arg) { return visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()); } : function () { return true; };        }        var onObjectBegin = toNoArgVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisit(visitor.onObjectProperty), onObjectEnd = toNoArgVisit(visitor.onObjectEnd), onArrayBegin = toNoArgVisit(visitor.onArrayBegin), onArrayEnd = toNoArgVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisit(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);        var disallowComments = options && options.disallowComments;        var allowTrailingComma = options && options.allowTrailingComma;        function scanNext() {            while (true) {                var token = _scanner.scan();                switch (_scanner.getTokenError()) {                    case 4 /* InvalidUnicode */:                        handleError(14 /* InvalidUnicode */);                        break;                    case 5 /* InvalidEscapeCharacter */:                        handleError(15 /* InvalidEscapeCharacter */);                        break;                    case 3 /* UnexpectedEndOfNumber */:                        handleError(13 /* UnexpectedEndOfNumber */);                        break;                    case 1 /* UnexpectedEndOfComment */:                        if (!disallowComments) {                            handleError(11 /* UnexpectedEndOfComment */);                        }                        break;                    case 2 /* UnexpectedEndOfString */:                        handleError(12 /* UnexpectedEndOfString */);                        break;                    case 6 /* InvalidCharacter */:                        handleError(16 /* InvalidCharacter */);                        break;                }                switch (token) {                    case 12 /* LineCommentTrivia */:                    case 13 /* BlockCommentTrivia */:                        if (disallowComments) {                            handleError(10 /* InvalidCommentToken */);                        }                        else {                            onComment();                        }                        break;                    case 16 /* Unknown */:                        handleError(1 /* InvalidSymbol */);                        break;                    case 15 /* Trivia */:                    case 14 /* LineBreakTrivia */:                        break;                    default:                        return token;                }            }        }        function handleError(error, skipUntilAfter, skipUntil) {            if (skipUntilAfter === void 0) { skipUntilAfter = []; }            if (skipUntil === void 0) { skipUntil = []; }            onError(error);            if (skipUntilAfter.length + skipUntil.length > 0) {                var token = _scanner.getToken();                while (token !== 17 /* EOF */) {                    if (skipUntilAfter.indexOf(token) !== -1) {                        scanNext();                        break;                    }                    else if (skipUntil.indexOf(token) !== -1) {                        break;                    }                    token = scanNext();                }            }        }        function parseString(isValue) {            var value = _scanner.getTokenValue();            if (isValue) {                onLiteralValue(value);            }            else {                onObjectProperty(value);            }            scanNext();            return true;        }        function parseLiteral() {            switch (_scanner.getToken()) {                case 11 /* NumericLiteral */:                    var tokenValue = _scanner.getTokenValue();                    var value = Number(tokenValue);                    if (isNaN(value)) {                        handleError(2 /* InvalidNumberFormat */);                        value = 0;                    }                    onLiteralValue(value);                    break;                case 7 /* NullKeyword */:                    onLiteralValue(null);                    break;                case 8 /* TrueKeyword */:                    onLiteralValue(true);                    break;                case 9 /* FalseKeyword */:                    onLiteralValue(false);                    break;                default:                    return false;            }            scanNext();            return true;        }        function parseProperty() {            if (_scanner.getToken() !== 10 /* StringLiteral */) {                handleError(3 /* PropertyNameExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);                return false;            }            parseString(false);            if (_scanner.getToken() === 6 /* ColonToken */) {                onSeparator(':');                scanNext(); // consume colon                if (!parseValue()) {                    handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);                }            }            else {                handleError(5 /* ColonExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);            }            return true;        }        function parseObject() {            onObjectBegin();            scanNext(); // consume open brace            var needsComma = false;            while (_scanner.getToken() !== 2 /* CloseBraceToken */ && _scanner.getToken() !== 17 /* EOF */) {                if (_scanner.getToken() === 5 /* CommaToken */) {                    if (!needsComma) {                        handleError(4 /* ValueExpected */, [], []);                    }                    onSeparator(',');                    scanNext(); // consume comma                    if (_scanner.getToken() === 2 /* CloseBraceToken */ && allowTrailingComma) {                        break;                    }                }                else if (needsComma) {                    handleError(6 /* CommaExpected */, [], []);                }                if (!parseProperty()) {                    handleError(4 /* ValueExpected */, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);                }                needsComma = true;            }            onObjectEnd();            if (_scanner.getToken() !== 2 /* CloseBraceToken */) {                handleError(7 /* CloseBraceExpected */, [2 /* CloseBraceToken */], []);            }            else {                scanNext(); // consume close brace            }            return true;        }        function parseArray() {            onArrayBegin();            scanNext(); // consume open bracket            var needsComma = false;            while (_scanner.getToken() !== 4 /* CloseBracketToken */ && _scanner.getToken() !== 17 /* EOF */) {                if (_scanner.getToken() === 5 /* CommaToken */) {                    if (!needsComma) {                        handleError(4 /* ValueExpected */, [], []);                    }                    onSeparator(',');                    scanNext(); // consume comma                    if (_scanner.getToken() === 4 /* CloseBracketToken */ && allowTrailingComma) {                        break;                    }                }                else if (needsComma) {                    handleError(6 /* CommaExpected */, [], []);                }                if (!parseValue()) {                    handleError(4 /* ValueExpected */, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);                }                needsComma = true;            }            onArrayEnd();            if (_scanner.getToken() !== 4 /* CloseBracketToken */) {                handleError(8 /* CloseBracketExpected */, [4 /* CloseBracketToken */], []);            }            else {                scanNext(); // consume close bracket            }            return true;        }        function parseValue() {            switch (_scanner.getToken()) {                case 3 /* OpenBracketToken */:                    return parseArray();                case 1 /* OpenBraceToken */:                    return parseObject();                case 10 /* StringLiteral */:                    return parseString(true);                default:                    return parseLiteral();            }        }        scanNext();        if (_scanner.getToken() === 17 /* EOF */) {            if (options.allowEmptyContent) {                return true;            }            handleError(4 /* ValueExpected */, [], []);            return false;        }        if (!parseValue()) {            handleError(4 /* ValueExpected */, [], []);            return false;        }        if (_scanner.getToken() !== 17 /* EOF */) {            handleError(9 /* EndOfFileExpected */, [], []);        }        return true;    }    exports.visit = visit;    /**     * Takes JSON with JavaScript-style comments and remove     * them. Optionally replaces every none-newline character     * of comments with a replaceCharacter     */    function stripComments(text, replaceCh) {        var _scanner = scanner_1.createScanner(text), parts = [], kind, offset = 0, pos;        do {            pos = _scanner.getPosition();            kind = _scanner.scan();            switch (kind) {                case 12 /* LineCommentTrivia */:                case 13 /* BlockCommentTrivia */:                case 17 /* EOF */:                    if (offset !== pos) {                        parts.push(text.substring(offset, pos));                    }                    if (replaceCh !== undefined) {                        parts.push(_scanner.getTokenValue().replace(/[^\r\n]/g, replaceCh));                    }                    offset = _scanner.getPosition();                    break;            }        } while (kind !== 17 /* EOF */);        return parts.join('');    }    exports.stripComments = stripComments;    function getNodeType(value) {        switch (typeof value) {            case 'boolean': return 'boolean';            case 'number': return 'number';            case 'string': return 'string';            case 'object': {                if (!value) {                    return 'null';                }                else if (Array.isArray(value)) {                    return 'array';                }                return 'object';            }            default: return 'null';        }    }    exports.getNodeType = getNodeType;});
 |