343 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
ace.define("ace/ext/beautify",["require","exports","module","ace/token_iterator"], function(require, exports, module){/**
 | 
						|
 * ## Code beautification and formatting extension.
 | 
						|
 *
 | 
						|
 * **This extension is considered outdated.** For better formatting support with modern language servers
 | 
						|
 * and advanced formatting capabilities, consider using [ace-linters](https://github.com/mkslanc/ace-linters)
 | 
						|
 * which provides comprehensive language support including formatting, linting, and IntelliSense features.
 | 
						|
 *
 | 
						|
 * This legacy extension provides basic formatting for HTML, CSS, JavaScript, and PHP code with support for
 | 
						|
 * proper indentation, whitespace management, line breaks, and bracket alignment. It handles various language
 | 
						|
 * constructs including HTML tags, CSS selectors, JavaScript operators, control structures, and maintains
 | 
						|
 * consistent code style throughout the document.
 | 
						|
 *
 | 
						|
 * @module
 | 
						|
 */
 | 
						|
"use strict";
 | 
						|
var TokenIterator = require("../token_iterator").TokenIterator;
 | 
						|
function is(token, type) {
 | 
						|
    return token.type.lastIndexOf(type + ".xml") > -1;
 | 
						|
}
 | 
						|
exports.singletonTags = ["area", "base", "br", "col", "command", "embed", "hr", "html", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"];
 | 
						|
exports.blockTags = ["article", "aside", "blockquote", "body", "div", "dl", "fieldset", "footer", "form", "head", "header", "html", "nav", "ol", "p", "script", "section", "style", "table", "tbody", "tfoot", "thead", "ul"];
 | 
						|
exports.formatOptions = {
 | 
						|
    lineBreaksAfterCommasInCurlyBlock: true
 | 
						|
};
 | 
						|
exports.beautify = function (session) {
 | 
						|
    var iterator = new TokenIterator(session, 0, 0);
 | 
						|
    var token = iterator.getCurrentToken();
 | 
						|
    var tabString = session.getTabString();
 | 
						|
    var singletonTags = exports.singletonTags;
 | 
						|
    var blockTags = exports.blockTags;
 | 
						|
    var formatOptions = exports.formatOptions || {};
 | 
						|
    var nextToken;
 | 
						|
    var breakBefore = false;
 | 
						|
    var spaceBefore = false;
 | 
						|
    var spaceAfter = false;
 | 
						|
    var code = "";
 | 
						|
    var value = "";
 | 
						|
    var tagName = "";
 | 
						|
    var depth = 0;
 | 
						|
    var lastDepth = 0;
 | 
						|
    var lastIndent = 0;
 | 
						|
    var indent = 0;
 | 
						|
    var unindent = 0;
 | 
						|
    var roundDepth = 0;
 | 
						|
    var curlyDepth = 0;
 | 
						|
    var row;
 | 
						|
    var curRow = 0;
 | 
						|
    var rowsToAdd = 0;
 | 
						|
    var rowTokens = [];
 | 
						|
    var abort = false;
 | 
						|
    var i;
 | 
						|
    var indentNextLine = false;
 | 
						|
    var inTag = false;
 | 
						|
    var inCSS = false;
 | 
						|
    var inBlock = false;
 | 
						|
    var levels = { 0: 0 };
 | 
						|
    var parents = [];
 | 
						|
    var caseBody = false;
 | 
						|
    var trimNext = function () {
 | 
						|
        if (nextToken && nextToken.value && nextToken.type !== 'string.regexp')
 | 
						|
            nextToken.value = nextToken.value.replace(/^\s*/, "");
 | 
						|
    };
 | 
						|
    var trimLine = function () {
 | 
						|
        var end = code.length - 1;
 | 
						|
        while (true) {
 | 
						|
            if (end == 0)
 | 
						|
                break;
 | 
						|
            if (code[end] !== " ")
 | 
						|
                break;
 | 
						|
            end = end - 1;
 | 
						|
        }
 | 
						|
        code = code.slice(0, end + 1);
 | 
						|
    };
 | 
						|
    var trimCode = function () {
 | 
						|
        code = code.trimRight();
 | 
						|
        breakBefore = false;
 | 
						|
    };
 | 
						|
    while (token !== null) {
 | 
						|
        curRow = iterator.getCurrentTokenRow();
 | 
						|
        rowTokens = iterator.$rowTokens;
 | 
						|
        nextToken = iterator.stepForward();
 | 
						|
        if (typeof token !== "undefined") {
 | 
						|
            value = token.value;
 | 
						|
            unindent = 0;
 | 
						|
            inCSS = (tagName === "style" || session.$modeId === "ace/mode/css");
 | 
						|
            if (is(token, "tag-open")) {
 | 
						|
                inTag = true;
 | 
						|
                if (nextToken)
 | 
						|
                    inBlock = (blockTags.indexOf(nextToken.value) !== -1);
 | 
						|
                if (value === "</") {
 | 
						|
                    if (inBlock && !breakBefore && rowsToAdd < 1)
 | 
						|
                        rowsToAdd++;
 | 
						|
                    if (inCSS)
 | 
						|
                        rowsToAdd = 1;
 | 
						|
                    unindent = 1;
 | 
						|
                    inBlock = false;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else if (is(token, "tag-close")) {
 | 
						|
                inTag = false;
 | 
						|
            }
 | 
						|
            else if (is(token, "comment.start")) {
 | 
						|
                inBlock = true;
 | 
						|
            }
 | 
						|
            else if (is(token, "comment.end")) {
 | 
						|
                inBlock = false;
 | 
						|
            }
 | 
						|
            if (!inTag && !rowsToAdd && token.type === "paren.rparen" && token.value.substr(0, 1) === "}") {
 | 
						|
                rowsToAdd++;
 | 
						|
            }
 | 
						|
            if (curRow !== row) {
 | 
						|
                rowsToAdd = curRow;
 | 
						|
                if (row)
 | 
						|
                    rowsToAdd -= row;
 | 
						|
            }
 | 
						|
            if (rowsToAdd) {
 | 
						|
                trimCode();
 | 
						|
                for (; rowsToAdd > 0; rowsToAdd--)
 | 
						|
                    code += "\n";
 | 
						|
                breakBefore = true;
 | 
						|
                if (!is(token, "comment") && !token.type.match(/^(comment|string)$/))
 | 
						|
                    value = value.trimLeft();
 | 
						|
            }
 | 
						|
            if (value) {
 | 
						|
                if (token.type === "keyword" && value.match(/^(if|else|elseif|for|foreach|while|switch)$/)) {
 | 
						|
                    parents[depth] = value;
 | 
						|
                    trimNext();
 | 
						|
                    spaceAfter = true;
 | 
						|
                    if (value.match(/^(else|elseif)$/)) {
 | 
						|
                        if (code.match(/\}[\s]*$/)) {
 | 
						|
                            trimCode();
 | 
						|
                            spaceBefore = true;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else if (token.type === "paren.lparen") {
 | 
						|
                    trimNext();
 | 
						|
                    if (value.substr(-1) === "{") {
 | 
						|
                        spaceAfter = true;
 | 
						|
                        indentNextLine = false;
 | 
						|
                        if (!inTag)
 | 
						|
                            rowsToAdd = 1;
 | 
						|
                    }
 | 
						|
                    if (value.substr(0, 1) === "{") {
 | 
						|
                        spaceBefore = true;
 | 
						|
                        if (code.substr(-1) !== '[' && code.trimRight().substr(-1) === '[') {
 | 
						|
                            trimCode();
 | 
						|
                            spaceBefore = false;
 | 
						|
                        }
 | 
						|
                        else if (code.trimRight().substr(-1) === ')') {
 | 
						|
                            trimCode();
 | 
						|
                        }
 | 
						|
                        else {
 | 
						|
                            trimLine();
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else if (token.type === "paren.rparen") {
 | 
						|
                    unindent = 1;
 | 
						|
                    if (value.substr(0, 1) === "}") {
 | 
						|
                        if (parents[depth - 1] === 'case')
 | 
						|
                            unindent++;
 | 
						|
                        if (code.trimRight().substr(-1) === '{') {
 | 
						|
                            trimCode();
 | 
						|
                        }
 | 
						|
                        else {
 | 
						|
                            spaceBefore = true;
 | 
						|
                            if (inCSS)
 | 
						|
                                rowsToAdd += 2;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if (value.substr(0, 1) === "]") {
 | 
						|
                        if (code.substr(-1) !== '}' && code.trimRight().substr(-1) === '}') {
 | 
						|
                            spaceBefore = false;
 | 
						|
                            indent++;
 | 
						|
                            trimCode();
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    if (value.substr(0, 1) === ")") {
 | 
						|
                        if (code.substr(-1) !== '(' && code.trimRight().substr(-1) === '(') {
 | 
						|
                            spaceBefore = false;
 | 
						|
                            indent++;
 | 
						|
                            trimCode();
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    trimLine();
 | 
						|
                }
 | 
						|
                else if ((token.type === "keyword.operator" || token.type === "keyword") && value.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=|=>)$/)) {
 | 
						|
                    trimCode();
 | 
						|
                    trimNext();
 | 
						|
                    spaceBefore = true;
 | 
						|
                    spaceAfter = true;
 | 
						|
                }
 | 
						|
                else if (token.type === "punctuation.operator" && value === ';') {
 | 
						|
                    trimCode();
 | 
						|
                    trimNext();
 | 
						|
                    spaceAfter = true;
 | 
						|
                    if (inCSS)
 | 
						|
                        rowsToAdd++;
 | 
						|
                }
 | 
						|
                else if (token.type === "punctuation.operator" && value.match(/^(:|,)$/)) {
 | 
						|
                    trimCode();
 | 
						|
                    trimNext();
 | 
						|
                    if (value.match(/^(,)$/) && curlyDepth > 0 && roundDepth === 0 && formatOptions.lineBreaksAfterCommasInCurlyBlock) {
 | 
						|
                        rowsToAdd++;
 | 
						|
                    }
 | 
						|
                    else {
 | 
						|
                        spaceAfter = true;
 | 
						|
                        breakBefore = false;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else if (token.type === "support.php_tag" && value === "?>" && !breakBefore) {
 | 
						|
                    trimCode();
 | 
						|
                    spaceBefore = true;
 | 
						|
                }
 | 
						|
                else if (is(token, "attribute-name") && code.substr(-1).match(/^\s$/)) {
 | 
						|
                    spaceBefore = true;
 | 
						|
                }
 | 
						|
                else if (is(token, "attribute-equals")) {
 | 
						|
                    trimLine();
 | 
						|
                    trimNext();
 | 
						|
                }
 | 
						|
                else if (is(token, "tag-close")) {
 | 
						|
                    trimLine();
 | 
						|
                    if (value === "/>")
 | 
						|
                        spaceBefore = true;
 | 
						|
                }
 | 
						|
                else if (token.type === "keyword" && value.match(/^(case|default)$/)) {
 | 
						|
                    if (caseBody)
 | 
						|
                        unindent = 1;
 | 
						|
                }
 | 
						|
                if (breakBefore && !(token.type.match(/^(comment)$/) && !value.substr(0, 1).match(/^[/#]$/)) && !(token.type.match(/^(string)$/) && !value.substr(0, 1).match(/^['"@]$/))) {
 | 
						|
                    indent = lastIndent;
 | 
						|
                    if (depth > lastDepth) {
 | 
						|
                        indent++;
 | 
						|
                        for (i = depth; i > lastDepth; i--)
 | 
						|
                            levels[i] = indent;
 | 
						|
                    }
 | 
						|
                    else if (depth < lastDepth)
 | 
						|
                        indent = levels[depth];
 | 
						|
                    lastDepth = depth;
 | 
						|
                    lastIndent = indent;
 | 
						|
                    if (unindent)
 | 
						|
                        indent -= unindent;
 | 
						|
                    if (indentNextLine && !roundDepth) {
 | 
						|
                        indent++;
 | 
						|
                        indentNextLine = false;
 | 
						|
                    }
 | 
						|
                    for (i = 0; i < indent; i++)
 | 
						|
                        code += tabString;
 | 
						|
                }
 | 
						|
                if (token.type === "keyword" && value.match(/^(case|default)$/)) {
 | 
						|
                    if (caseBody === false) {
 | 
						|
                        parents[depth] = value;
 | 
						|
                        depth++;
 | 
						|
                        caseBody = true;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else if (token.type === "keyword" && value.match(/^(break)$/)) {
 | 
						|
                    if (parents[depth - 1] && parents[depth - 1].match(/^(case|default)$/)) {
 | 
						|
                        depth--;
 | 
						|
                        caseBody = false;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (token.type === "paren.lparen") {
 | 
						|
                    roundDepth += (value.match(/\(/g) || []).length;
 | 
						|
                    curlyDepth += (value.match(/\{/g) || []).length;
 | 
						|
                    depth += value.length;
 | 
						|
                }
 | 
						|
                if (token.type === "keyword" && value.match(/^(if|else|elseif|for|while)$/)) {
 | 
						|
                    indentNextLine = true;
 | 
						|
                    roundDepth = 0;
 | 
						|
                }
 | 
						|
                else if (!roundDepth && value.trim() && token.type !== "comment")
 | 
						|
                    indentNextLine = false;
 | 
						|
                if (token.type === "paren.rparen") {
 | 
						|
                    roundDepth -= (value.match(/\)/g) || []).length;
 | 
						|
                    curlyDepth -= (value.match(/\}/g) || []).length;
 | 
						|
                    for (i = 0; i < value.length; i++) {
 | 
						|
                        depth--;
 | 
						|
                        if (value.substr(i, 1) === '}' && parents[depth] === 'case') {
 | 
						|
                            depth--;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (token.type == "text")
 | 
						|
                    value = value.replace(/\s+$/, " ");
 | 
						|
                if (spaceBefore && !breakBefore) {
 | 
						|
                    trimLine();
 | 
						|
                    if (code.substr(-1) !== "\n")
 | 
						|
                        code += " ";
 | 
						|
                }
 | 
						|
                code += value;
 | 
						|
                if (spaceAfter)
 | 
						|
                    code += " ";
 | 
						|
                breakBefore = false;
 | 
						|
                spaceBefore = false;
 | 
						|
                spaceAfter = false;
 | 
						|
                if ((is(token, "tag-close") && (inBlock || blockTags.indexOf(tagName) !== -1)) || (is(token, "doctype") && value === ">")) {
 | 
						|
                    if (inBlock && nextToken && nextToken.value === "</")
 | 
						|
                        rowsToAdd = -1;
 | 
						|
                    else
 | 
						|
                        rowsToAdd = 1;
 | 
						|
                }
 | 
						|
                if (nextToken && singletonTags.indexOf(nextToken.value) === -1) {
 | 
						|
                    if (is(token, "tag-open") && value === "</") {
 | 
						|
                        depth--;
 | 
						|
                    }
 | 
						|
                    else if (is(token, "tag-open") && value === "<") {
 | 
						|
                        depth++;
 | 
						|
                    }
 | 
						|
                    else if (is(token, "tag-close") && value === "/>") {
 | 
						|
                        depth--;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (is(token, "tag-name")) {
 | 
						|
                    tagName = value;
 | 
						|
                }
 | 
						|
                row = curRow;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        token = nextToken;
 | 
						|
    }
 | 
						|
    code = code.trim();
 | 
						|
    session.doc.setValue(code);
 | 
						|
};
 | 
						|
exports.commands = [{
 | 
						|
        name: "beautify",
 | 
						|
        description: "Format selection (Beautify)",
 | 
						|
        exec: function (editor) {
 | 
						|
            exports.beautify(editor.session);
 | 
						|
        },
 | 
						|
        bindKey: "Ctrl-Shift-B"
 | 
						|
    }];
 | 
						|
 | 
						|
});                (function() {
 | 
						|
                    ace.require(["ace/ext/beautify"], function(m) {
 | 
						|
                        if (typeof module == "object" && typeof exports == "object" && module) {
 | 
						|
                            module.exports = m;
 | 
						|
                        }
 | 
						|
                    });
 | 
						|
                })();
 | 
						|
            
 |