/*!-----------------------------------------------------------
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Version: 0.2.3(84e204b238a1eff25d4c6f611fdcd76a494005a7)
 * Released under the MIT license
 * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt
 *-----------------------------------------------------------*/

/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
define("vs/languages/html/common/htmlEmptyTagsShared", ["require", "exports", 'vs/base/common/arrays'], function (require, exports, arrays) {
    "use strict";
    exports.EMPTY_ELEMENTS = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
    function isEmptyElement(e) {
        return arrays.binarySearch(exports.EMPTY_ELEMENTS, e, function (s1, s2) { return s1.localeCompare(s2); }) >= 0;
    }
    exports.isEmptyElement = isEmptyElement;
});

define("vs/languages/html/common/htmlTokenTypes", ["require", "exports", 'vs/base/common/strings'], function (require, exports, strings) {
    /*---------------------------------------------------------------------------------------------
     *  Copyright (c) Microsoft Corporation. All rights reserved.
     *  Licensed under the MIT License. See License.txt in the project root for license information.
     *--------------------------------------------------------------------------------------------*/
    'use strict';
    exports.DELIM_END = 'punctuation.definition.meta.tag.end.html';
    exports.DELIM_START = 'punctuation.definition.meta.tag.begin.html';
    exports.DELIM_ASSIGN = 'meta.tag.assign.html';
    exports.ATTRIB_NAME = 'entity.other.attribute-name.html';
    exports.ATTRIB_VALUE = 'string.html';
    exports.COMMENT = 'comment.html.content';
    exports.DELIM_COMMENT = 'comment.html';
    exports.DOCTYPE = 'entity.other.attribute-name.html';
    exports.DELIM_DOCTYPE = 'entity.name.tag.html';
    var TAG_PREFIX = 'entity.name.tag.tag-';
    function isTag(tokenType) {
        return strings.startsWith(tokenType, TAG_PREFIX);
    }
    exports.isTag = isTag;
    function getTag(name) {
        return TAG_PREFIX + name;
    }
    exports.getTag = getTag;
});

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
define("vs/languages/html/common/html", ["require", "exports", 'vs/base/common/winjs.base', 'vs/editor/common/modes', 'vs/editor/common/modes/abstractMode', 'vs/editor/common/modes/abstractState', 'vs/platform/thread/common/threadService', 'vs/editor/common/services/modeService', 'vs/platform/instantiation/common/instantiation', 'vs/languages/html/common/htmlTokenTypes', 'vs/languages/html/common/htmlEmptyTagsShared', 'vs/editor/common/modes/supports/richEditSupport', 'vs/editor/common/modes/supports/tokenizationSupport', 'vs/platform/thread/common/thread', 'vs/base/common/async'], function (require, exports, winjs, modes, abstractMode_1, abstractState_1, threadService_1, modeService_1, instantiation_1, htmlTokenTypes, htmlEmptyTagsShared_1, richEditSupport_1, tokenizationSupport_1, thread_1, async_1) {
    /*---------------------------------------------------------------------------------------------
     *  Copyright (c) Microsoft Corporation. All rights reserved.
     *  Licensed under the MIT License. See License.txt in the project root for license information.
     *--------------------------------------------------------------------------------------------*/
    'use strict';
    exports.htmlTokenTypes = htmlTokenTypes;
    exports.EMPTY_ELEMENTS = htmlEmptyTagsShared_1.EMPTY_ELEMENTS;
     // export to be used by Razor. We are the main module, so Razor should get it from us.
     // export to be used by Razor. We are the main module, so Razor should get it from us.
    (function (States) {
        States[States["Content"] = 0] = "Content";
        States[States["OpeningStartTag"] = 1] = "OpeningStartTag";
        States[States["OpeningEndTag"] = 2] = "OpeningEndTag";
        States[States["WithinDoctype"] = 3] = "WithinDoctype";
        States[States["WithinTag"] = 4] = "WithinTag";
        States[States["WithinComment"] = 5] = "WithinComment";
        States[States["WithinEmbeddedContent"] = 6] = "WithinEmbeddedContent";
        States[States["AttributeName"] = 7] = "AttributeName";
        States[States["AttributeValue"] = 8] = "AttributeValue";
    })(exports.States || (exports.States = {}));
    var States = exports.States;
    // list of elements that embed other content
    var tagsEmbeddingContent = ['script', 'style'];
    var State = (function (_super) {
        __extends(State, _super);
        function State(mode, kind, lastTagName, lastAttributeName, embeddedContentType, attributeValueQuote, attributeValue) {
            _super.call(this, mode);
            this.kind = kind;
            this.lastTagName = lastTagName;
            this.lastAttributeName = lastAttributeName;
            this.embeddedContentType = embeddedContentType;
            this.attributeValueQuote = attributeValueQuote;
            this.attributeValue = attributeValue;
        }
        State.escapeTagName = function (s) {
            return htmlTokenTypes.getTag(s.replace(/[:_.]/g, '-'));
        };
        State.prototype.makeClone = function () {
            return new State(this.getMode(), this.kind, this.lastTagName, this.lastAttributeName, this.embeddedContentType, this.attributeValueQuote, this.attributeValue);
        };
        State.prototype.equals = function (other) {
            if (other instanceof State) {
                return (_super.prototype.equals.call(this, other) &&
                    this.kind === other.kind &&
                    this.lastTagName === other.lastTagName &&
                    this.lastAttributeName === other.lastAttributeName &&
                    this.embeddedContentType === other.embeddedContentType &&
                    this.attributeValueQuote === other.attributeValueQuote &&
                    this.attributeValue === other.attributeValue);
            }
            return false;
        };
        State.prototype.nextElementName = function (stream) {
            return stream.advanceIfRegExp(/^[_:\w][_:\w-.\d]*/).toLowerCase();
        };
        State.prototype.nextAttributeName = function (stream) {
            return stream.advanceIfRegExp(/^[^\s"'>/=\x00-\x0F\x7F\x80-\x9F]*/).toLowerCase();
        };
        State.prototype.tokenize = function (stream) {
            switch (this.kind) {
                case States.WithinComment:
                    if (stream.advanceUntilString2('-->', false)) {
                        return { type: htmlTokenTypes.COMMENT };
                    }
                    else if (stream.advanceIfString2('-->')) {
                        this.kind = States.Content;
                        return { type: htmlTokenTypes.DELIM_COMMENT, dontMergeWithPrev: true };
                    }
                    break;
                case States.WithinDoctype:
                    if (stream.advanceUntilString2('>', false)) {
                        return { type: htmlTokenTypes.DOCTYPE };
                    }
                    else if (stream.advanceIfString2('>')) {
                        this.kind = States.Content;
                        return { type: htmlTokenTypes.DELIM_DOCTYPE, dontMergeWithPrev: true };
                    }
                    break;
                case States.Content:
                    if (stream.advanceIfCharCode2('<'.charCodeAt(0))) {
                        if (!stream.eos() && stream.peek() === '!') {
                            if (stream.advanceIfString2('!--')) {
                                this.kind = States.WithinComment;
                                return { type: htmlTokenTypes.DELIM_COMMENT, dontMergeWithPrev: true };
                            }
                            if (stream.advanceIfStringCaseInsensitive2('!DOCTYPE')) {
                                this.kind = States.WithinDoctype;
                                return { type: htmlTokenTypes.DELIM_DOCTYPE, dontMergeWithPrev: true };
                            }
                        }
                        if (stream.advanceIfCharCode2('/'.charCodeAt(0))) {
                            this.kind = States.OpeningEndTag;
                            return { type: htmlTokenTypes.DELIM_END, dontMergeWithPrev: true };
                        }
                        this.kind = States.OpeningStartTag;
                        return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true };
                    }
                    break;
                case States.OpeningEndTag:
                    var tagName = this.nextElementName(stream);
                    if (tagName.length > 0) {
                        return {
                            type: State.escapeTagName(tagName),
                        };
                    }
                    else if (stream.advanceIfString2('>')) {
                        this.kind = States.Content;
                        return { type: htmlTokenTypes.DELIM_END, dontMergeWithPrev: true };
                    }
                    else {
                        stream.advanceUntilString2('>', false);
                        return { type: '' };
                    }
                case States.OpeningStartTag:
                    this.lastTagName = this.nextElementName(stream);
                    if (this.lastTagName.length > 0) {
                        this.lastAttributeName = null;
                        if ('script' === this.lastTagName || 'style' === this.lastTagName) {
                            this.lastAttributeName = null;
                            this.embeddedContentType = null;
                        }
                        this.kind = States.WithinTag;
                        return {
                            type: State.escapeTagName(this.lastTagName),
                        };
                    }
                    break;
                case States.WithinTag:
                    if (stream.skipWhitespace2() || stream.eos()) {
                        this.lastAttributeName = ''; // remember that we have seen a whitespace
                        return { type: '' };
                    }
                    else {
                        if (this.lastAttributeName === '') {
                            var name = this.nextAttributeName(stream);
                            if (name.length > 0) {
                                this.lastAttributeName = name;
                                this.kind = States.AttributeName;
                                return { type: htmlTokenTypes.ATTRIB_NAME };
                            }
                        }
                        if (stream.advanceIfString2('/>')) {
                            this.kind = States.Content;
                            return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true };
                        }
                        if (stream.advanceIfCharCode2('>'.charCodeAt(0))) {
                            if (tagsEmbeddingContent.indexOf(this.lastTagName) !== -1) {
                                this.kind = States.WithinEmbeddedContent;
                                return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true };
                            }
                            else {
                                this.kind = States.Content;
                                return { type: htmlTokenTypes.DELIM_START, dontMergeWithPrev: true };
                            }
                        }
                        else {
                            stream.next2();
                            return { type: '' };
                        }
                    }
                case States.AttributeName:
                    if (stream.skipWhitespace2() || stream.eos()) {
                        return { type: '' };
                    }
                    if (stream.advanceIfCharCode2('='.charCodeAt(0))) {
                        this.kind = States.AttributeValue;
                        return { type: htmlTokenTypes.DELIM_ASSIGN };
                    }
                    else {
                        this.kind = States.WithinTag;
                        this.lastAttributeName = '';
                        return this.tokenize(stream); // no advance yet - jump to WithinTag
                    }
                case States.AttributeValue:
                    if (stream.eos()) {
                        return { type: '' };
                    }
                    if (stream.skipWhitespace2()) {
                        if (this.attributeValueQuote === '"' || this.attributeValueQuote === '\'') {
                            // We are inside the quotes of an attribute value
                            return { type: htmlTokenTypes.ATTRIB_VALUE };
                        }
                        return { type: '' };
                    }
                    // We are in a attribute value
                    if (this.attributeValueQuote === '"' || this.attributeValueQuote === '\'') {
                        if (this.attributeValue === this.attributeValueQuote && ('script' === this.lastTagName || 'style' === this.lastTagName) && 'type' === this.lastAttributeName) {
                            this.attributeValue = stream.advanceUntilString(this.attributeValueQuote, true);
                            if (this.attributeValue.length > 0) {
                                this.embeddedContentType = this.unquote(this.attributeValue);
                                this.kind = States.WithinTag;
                                this.attributeValue = '';
                                this.attributeValueQuote = '';
                                return { type: htmlTokenTypes.ATTRIB_VALUE };
                            }
                        }
                        else {
                            if (stream.advanceIfCharCode2(this.attributeValueQuote.charCodeAt(0))) {
                                this.kind = States.WithinTag;
                                this.attributeValue = '';
                                this.attributeValueQuote = '';
                                this.lastAttributeName = null;
                            }
                            else {
                                var part = stream.next();
                                this.attributeValue += part;
                            }
                            return { type: htmlTokenTypes.ATTRIB_VALUE };
                        }
                    }
                    else {
                        var attributeValue = stream.advanceIfRegExp(/^[^\s"'`=<>]+/);
                        if (attributeValue.length > 0) {
                            this.kind = States.WithinTag;
                            this.lastAttributeName = null;
                            return { type: htmlTokenTypes.ATTRIB_VALUE };
                        }
                        var ch = stream.peek();
                        if (ch === '\'' || ch === '"') {
                            this.attributeValueQuote = ch;
                            this.attributeValue = ch;
                            stream.next2();
                            return { type: htmlTokenTypes.ATTRIB_VALUE };
                        }
                        else {
                            this.kind = States.WithinTag;
                            this.lastAttributeName = null;
                            return this.tokenize(stream); // no advance yet - jump to WithinTag
                        }
                    }
            }
            stream.next2();
            this.kind = States.Content;
            return { type: '' };
        };
        State.prototype.unquote = function (value) {
            var start = 0;
            var end = value.length;
            if ('"' === value[0]) {
                start++;
            }
            if ('"' === value[end - 1]) {
                end--;
            }
            return value.substring(start, end);
        };
        return State;
    }(abstractState_1.AbstractState));
    exports.State = State;
    var HTMLMode = (function (_super) {
        __extends(HTMLMode, _super);
        function HTMLMode(descriptor, instantiationService, modeService, threadService) {
            _super.call(this, descriptor.id);
            this._modeWorkerManager = this._createModeWorkerManager(descriptor, instantiationService);
            this.modeService = modeService;
            this.threadService = threadService;
            this.tokenizationSupport = new tokenizationSupport_1.TokenizationSupport(this, this, true, true);
            this.configSupport = this;
            this.richEditSupport = this._createRichEditSupport();
            this._registerSupports();
        }
        HTMLMode.prototype.asyncCtor = function () {
            return winjs.Promise.join([
                this.modeService.getOrCreateMode('text/css'),
                this.modeService.getOrCreateMode('text/javascript'),
            ]);
        };
        HTMLMode.prototype._registerSupports = function () {
            var _this = this;
            if (this.getId() !== 'html') {
                throw new Error('This method must be overwritten!');
            }
            modes.HoverProviderRegistry.register(this.getId(), {
                provideHover: function (model, position, token) {
                    return async_1.wireCancellationToken(token, _this._provideHover(model.uri, position));
                }
            }, true);
            modes.ReferenceProviderRegistry.register(this.getId(), {
                provideReferences: function (model, position, context, token) {
                    return async_1.wireCancellationToken(token, _this._provideReferences(model.uri, position, context));
                }
            }, true);
            modes.SuggestRegistry.register(this.getId(), {
                triggerCharacters: ['.', ':', '<', '"', '=', '/'],
                shouldAutotriggerSuggest: true,
                provideCompletionItems: function (model, position, token) {
                    return async_1.wireCancellationToken(token, _this._provideCompletionItems(model.uri, position));
                }
            }, true);
            modes.DocumentHighlightProviderRegistry.register(this.getId(), {
                provideDocumentHighlights: function (model, position, token) {
                    return async_1.wireCancellationToken(token, _this._provideDocumentHighlights(model.uri, position));
                }
            }, true);
            modes.DocumentRangeFormattingEditProviderRegistry.register(this.getId(), {
                provideDocumentRangeFormattingEdits: function (model, range, options, token) {
                    return async_1.wireCancellationToken(token, _this._provideDocumentRangeFormattingEdits(model.uri, range, options));
                }
            }, true);
            modes.LinkProviderRegistry.register(this.getId(), {
                provideLinks: function (model, token) {
                    return async_1.wireCancellationToken(token, _this._provideLinks(model.uri));
                }
            }, true);
        };
        HTMLMode.prototype._createModeWorkerManager = function (descriptor, instantiationService) {
            return new abstractMode_1.ModeWorkerManager(descriptor, 'vs/languages/html/common/htmlWorker', 'HTMLWorker', null, instantiationService);
        };
        HTMLMode.prototype._worker = function (runner) {
            return this._modeWorkerManager.worker(runner);
        };
        HTMLMode.prototype._createRichEditSupport = function () {
            return new richEditSupport_1.RichEditSupport(this.getId(), null, {
                wordPattern: abstractMode_1.createWordRegExp('#-?%'),
                comments: {
                    blockComment: ['<!--', '-->']
                },
                brackets: [
                    ['<!--', '-->'],
                    ['<', '>'],
                ],
                __electricCharacterSupport: {
                    caseInsensitive: true,
                    embeddedElectricCharacters: ['*', '}', ']', ')']
                },
                autoClosingPairs: [
                    { open: '{', close: '}' },
                    { open: '[', close: ']' },
                    { open: '(', close: ')' },
                    { open: '"', close: '"' },
                    { open: '\'', close: '\'' }
                ],
                surroundingPairs: [
                    { open: '"', close: '"' },
                    { open: '\'', close: '\'' }
                ],
                onEnterRules: [
                    {
                        beforeText: new RegExp("<(?!(?:" + htmlEmptyTagsShared_1.EMPTY_ELEMENTS.join('|') + "))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$", 'i'),
                        afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i,
                        action: { indentAction: modes.IndentAction.IndentOutdent }
                    },
                    {
                        beforeText: new RegExp("<(?!(?:" + htmlEmptyTagsShared_1.EMPTY_ELEMENTS.join('|') + "))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$", 'i'),
                        action: { indentAction: modes.IndentAction.Indent }
                    }
                ],
            });
        };
        // TokenizationSupport
        HTMLMode.prototype.getInitialState = function () {
            return new State(this, States.Content, '', '', '', '', '');
        };
        HTMLMode.prototype.enterNestedMode = function (state) {
            return state instanceof State && state.kind === States.WithinEmbeddedContent;
        };
        HTMLMode.prototype.getNestedMode = function (state) {
            var result = null;
            var htmlState = state;
            var missingModePromise = null;
            if (htmlState.embeddedContentType !== null) {
                if (this.modeService.isRegisteredMode(htmlState.embeddedContentType)) {
                    result = this.modeService.getMode(htmlState.embeddedContentType);
                    if (!result) {
                        missingModePromise = this.modeService.getOrCreateMode(htmlState.embeddedContentType);
                    }
                }
            }
            else {
                var mimeType = null;
                if ('script' === htmlState.lastTagName) {
                    mimeType = 'text/javascript';
                }
                else if ('style' === htmlState.lastTagName) {
                    mimeType = 'text/css';
                }
                else {
                    mimeType = 'text/plain';
                }
                result = this.modeService.getMode(mimeType);
            }
            if (result === null) {
                result = this.modeService.getMode('text/plain');
            }
            return {
                mode: result,
                missingModePromise: missingModePromise
            };
        };
        HTMLMode.prototype.getLeavingNestedModeData = function (line, state) {
            var tagName = state.lastTagName;
            var regexp = new RegExp('<\\/' + tagName + '\\s*>', 'i');
            var match = regexp.exec(line);
            if (match !== null) {
                return {
                    nestedModeBuffer: line.substring(0, match.index),
                    bufferAfterNestedMode: line.substring(match.index),
                    stateAfterNestedMode: new State(this, States.Content, '', '', '', '', '')
                };
            }
            return null;
        };
        HTMLMode.prototype.configure = function (options) {
            if (this.threadService.isInMainThread) {
                return this._configureWorkers(options);
            }
            else {
                return this._worker(function (w) { return w._doConfigure(options); });
            }
        };
        HTMLMode.prototype._configureWorkers = function (options) {
            return this._worker(function (w) { return w._doConfigure(options); });
        };
        HTMLMode.prototype._provideLinks = function (resource) {
            return this._worker(function (w) { return w.provideLinks(resource); });
        };
        HTMLMode.prototype._provideDocumentRangeFormattingEdits = function (resource, range, options) {
            return this._worker(function (w) { return w.provideDocumentRangeFormattingEdits(resource, range, options); });
        };
        HTMLMode.prototype._provideHover = function (resource, position) {
            return this._worker(function (w) { return w.provideHover(resource, position); });
        };
        HTMLMode.prototype._provideReferences = function (resource, position, context) {
            return this._worker(function (w) { return w.provideReferences(resource, position); });
        };
        HTMLMode.prototype._provideDocumentHighlights = function (resource, position, strict) {
            if (strict === void 0) { strict = false; }
            return this._worker(function (w) { return w.provideDocumentHighlights(resource, position, strict); });
        };
        HTMLMode.prototype._provideCompletionItems = function (resource, position) {
            return this._worker(function (w) { return w.provideCompletionItems(resource, position); });
        };
        HTMLMode.prototype.findColorDeclarations = function (resource) {
            return this._worker(function (w) { return w.findColorDeclarations(resource); });
        };
        HTMLMode.$_configureWorkers = threadService_1.AllWorkersAttr(HTMLMode, HTMLMode.prototype._configureWorkers);
        HTMLMode.$_provideLinks = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideLinks);
        HTMLMode.$_provideDocumentRangeFormattingEdits = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideDocumentRangeFormattingEdits);
        HTMLMode.$_provideHover = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideHover);
        HTMLMode.$_provideReferences = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideReferences);
        HTMLMode.$_provideDocumentHighlights = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideDocumentHighlights);
        HTMLMode.$_provideCompletionItems = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype._provideCompletionItems);
        HTMLMode.$findColorDeclarations = threadService_1.OneWorkerAttr(HTMLMode, HTMLMode.prototype.findColorDeclarations);
        HTMLMode = __decorate([
            __param(1, instantiation_1.IInstantiationService),
            __param(2, modeService_1.IModeService),
            __param(3, thread_1.IThreadService)
        ], HTMLMode);
        return HTMLMode;
    }(abstractMode_1.AbstractMode));
    exports.HTMLMode = HTMLMode;
});

//# sourceMappingURL=html.js.map
