|
@@ -1,540 +0,0 @@
|
|
-import {camelCase, kebabCase, snakeCase} from "lodash";
|
|
|
|
-import vkbeautify from "vkbeautify";
|
|
|
|
-import {DOMParser} from "xmldom";
|
|
|
|
-import xpath from "xpath";
|
|
|
|
-import jpath from "jsonpath";
|
|
|
|
-import nwmatcher from "nwmatcher";
|
|
|
|
-import hljs from "highlight.js";
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * Code operations.
|
|
|
|
- *
|
|
|
|
- * @author n1474335 [n1474335@gmail.com]
|
|
|
|
- * @copyright Crown Copyright 2016
|
|
|
|
- * @license Apache-2.0
|
|
|
|
- *
|
|
|
|
- * @namespace
|
|
|
|
- */
|
|
|
|
-const Code = {
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- LANGUAGES: ["auto detect"].concat(hljs.listLanguages()),
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Syntax highlighter operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {html}
|
|
|
|
- */
|
|
|
|
- runSyntaxHighlight: function(input, args) {
|
|
|
|
- const language = args[0];
|
|
|
|
-
|
|
|
|
- if (language === "auto detect") {
|
|
|
|
- return hljs.highlightAuto(input).value;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return hljs.highlight(language, input, true).value;
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- BEAUTIFY_INDENT: "\\t",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * XML Beautify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runXmlBeautify: function(input, args) {
|
|
|
|
- const indentStr = args[0];
|
|
|
|
- return vkbeautify.xml(input, indentStr);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * JSON Beautify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runJsonBeautify: function(input, args) {
|
|
|
|
- const indentStr = args[0];
|
|
|
|
- if (!input) return "";
|
|
|
|
- return vkbeautify.json(input, indentStr);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * CSS Beautify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runCssBeautify: function(input, args) {
|
|
|
|
- const indentStr = args[0];
|
|
|
|
- return vkbeautify.css(input, indentStr);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * SQL Beautify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runSqlBeautify: function(input, args) {
|
|
|
|
- const indentStr = args[0];
|
|
|
|
- return vkbeautify.sql(input, indentStr);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- PRESERVE_COMMENTS: false,
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * XML Minify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runXmlMinify: function(input, args) {
|
|
|
|
- const preserveComments = args[0];
|
|
|
|
- return vkbeautify.xmlmin(input, preserveComments);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * JSON Minify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runJsonMinify: function(input, args) {
|
|
|
|
- if (!input) return "";
|
|
|
|
- return vkbeautify.jsonmin(input);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * CSS Minify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runCssMinify: function(input, args) {
|
|
|
|
- const preserveComments = args[0];
|
|
|
|
- return vkbeautify.cssmin(input, preserveComments);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * SQL Minify operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runSqlMinify: function(input, args) {
|
|
|
|
- return vkbeautify.sqlmin(input);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Generic Code Beautify operation.
|
|
|
|
- *
|
|
|
|
- * Yeeeaaah...
|
|
|
|
- *
|
|
|
|
- * I'm not proud of this code, but seriously, try writing a generic lexer and parser that
|
|
|
|
- * correctly generates an AST for multiple different languages. I have tried, and I can tell
|
|
|
|
- * you it's pretty much impossible.
|
|
|
|
- *
|
|
|
|
- * This basically works. That'll have to be good enough. It's not meant to produce working code,
|
|
|
|
- * just slightly more readable code.
|
|
|
|
- *
|
|
|
|
- * Things that don't work:
|
|
|
|
- * - For loop formatting
|
|
|
|
- * - Do-While loop formatting
|
|
|
|
- * - Switch/Case indentation
|
|
|
|
- * - Bit shift operators
|
|
|
|
- *
|
|
|
|
- * @author n1474335 [n1474335@gmail.com]
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runGenericBeautify: function(input, args) {
|
|
|
|
- let code = input,
|
|
|
|
- t = 0,
|
|
|
|
- preservedTokens = [],
|
|
|
|
- m;
|
|
|
|
-
|
|
|
|
- // Remove strings
|
|
|
|
- const sstrings = /'([^'\\]|\\.)*'/g;
|
|
|
|
- while ((m = sstrings.exec(code))) {
|
|
|
|
- code = preserveToken(code, m, t++);
|
|
|
|
- sstrings.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const dstrings = /"([^"\\]|\\.)*"/g;
|
|
|
|
- while ((m = dstrings.exec(code))) {
|
|
|
|
- code = preserveToken(code, m, t++);
|
|
|
|
- dstrings.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Remove comments
|
|
|
|
- const scomments = /\/\/[^\n\r]*/g;
|
|
|
|
- while ((m = scomments.exec(code))) {
|
|
|
|
- code = preserveToken(code, m, t++);
|
|
|
|
- scomments.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const mcomments = /\/\*[\s\S]*?\*\//gm;
|
|
|
|
- while ((m = mcomments.exec(code))) {
|
|
|
|
- code = preserveToken(code, m, t++);
|
|
|
|
- mcomments.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const hcomments = /(^|\n)#[^\n\r#]+/g;
|
|
|
|
- while ((m = hcomments.exec(code))) {
|
|
|
|
- code = preserveToken(code, m, t++);
|
|
|
|
- hcomments.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Remove regexes
|
|
|
|
- const regexes = /\/.*?[^\\]\/[gim]{0,3}/gi;
|
|
|
|
- while ((m = regexes.exec(code))) {
|
|
|
|
- code = preserveToken(code, m, t++);
|
|
|
|
- regexes.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- code = code
|
|
|
|
- // Create newlines after ;
|
|
|
|
- .replace(/;/g, ";\n")
|
|
|
|
- // Create newlines after { and around }
|
|
|
|
- .replace(/{/g, "{\n")
|
|
|
|
- .replace(/}/g, "\n}\n")
|
|
|
|
- // Remove carriage returns
|
|
|
|
- .replace(/\r/g, "")
|
|
|
|
- // Remove all indentation
|
|
|
|
- .replace(/^\s+/g, "")
|
|
|
|
- .replace(/\n\s+/g, "\n")
|
|
|
|
- // Remove trailing spaces
|
|
|
|
- .replace(/\s*$/g, "")
|
|
|
|
- .replace(/\n{/g, "{");
|
|
|
|
-
|
|
|
|
- // Indent
|
|
|
|
- let i = 0,
|
|
|
|
- level = 0,
|
|
|
|
- indent;
|
|
|
|
- while (i < code.length) {
|
|
|
|
- switch (code[i]) {
|
|
|
|
- case "{":
|
|
|
|
- level++;
|
|
|
|
- break;
|
|
|
|
- case "\n":
|
|
|
|
- if (i+1 >= code.length) break;
|
|
|
|
-
|
|
|
|
- if (code[i+1] === "}") level--;
|
|
|
|
- indent = (level >= 0) ? Array(level*4+1).join(" ") : "";
|
|
|
|
-
|
|
|
|
- code = code.substring(0, i+1) + indent + code.substring(i+1);
|
|
|
|
- if (level > 0) i += level*4;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- i++;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- code = code
|
|
|
|
- // Add strategic spaces
|
|
|
|
- .replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ")
|
|
|
|
- .replace(/\s*<([=]?)\s*/g, " <$1 ")
|
|
|
|
- .replace(/\s*>([=]?)\s*/g, " >$1 ")
|
|
|
|
- .replace(/([^+])\+([^+=])/g, "$1 + $2")
|
|
|
|
- .replace(/([^-])-([^-=])/g, "$1 - $2")
|
|
|
|
- .replace(/([^*])\*([^*=])/g, "$1 * $2")
|
|
|
|
- .replace(/([^/])\/([^/=])/g, "$1 / $2")
|
|
|
|
- .replace(/\s*,\s*/g, ", ")
|
|
|
|
- .replace(/\s*{/g, " {")
|
|
|
|
- .replace(/}\n/g, "}\n\n")
|
|
|
|
- // Hacky horribleness
|
|
|
|
- .replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3")
|
|
|
|
- .replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3")
|
|
|
|
- .replace(/else\s*\n([^{])/gim, "else\n $1")
|
|
|
|
- .replace(/else\s+([^{])/gim, "else $1")
|
|
|
|
- // Remove strategic spaces
|
|
|
|
- .replace(/\s+;/g, ";")
|
|
|
|
- .replace(/\{\s+\}/g, "{}")
|
|
|
|
- .replace(/\[\s+\]/g, "[]")
|
|
|
|
- .replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
|
|
|
|
-
|
|
|
|
- // Replace preserved tokens
|
|
|
|
- const ptokens = /###preservedToken(\d+)###/g;
|
|
|
|
- while ((m = ptokens.exec(code))) {
|
|
|
|
- const ti = parseInt(m[1], 10);
|
|
|
|
- code = code.substring(0, m.index) + preservedTokens[ti] + code.substring(m.index + m[0].length);
|
|
|
|
- ptokens.lastIndex = m.index;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return code;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Replaces a matched token with a placeholder value.
|
|
|
|
- */
|
|
|
|
- function preserveToken(str, match, t) {
|
|
|
|
- preservedTokens[t] = match[0];
|
|
|
|
- return str.substring(0, match.index) +
|
|
|
|
- "###preservedToken" + t + "###" +
|
|
|
|
- str.substring(match.index + match[0].length);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- XPATH_INITIAL: "",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- XPATH_DELIMITER: "\\n",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * XPath expression operation.
|
|
|
|
- *
|
|
|
|
- * @author Mikescher (https://github.com/Mikescher | https://mikescher.com)
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runXpath: function(input, args) {
|
|
|
|
- let query = args[0],
|
|
|
|
- delimiter = args[1];
|
|
|
|
-
|
|
|
|
- let doc;
|
|
|
|
- try {
|
|
|
|
- doc = new DOMParser().parseFromString(input, "application/xml");
|
|
|
|
- } catch (err) {
|
|
|
|
- return "Invalid input XML.";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- let nodes;
|
|
|
|
- try {
|
|
|
|
- nodes = xpath.select(query, doc);
|
|
|
|
- } catch (err) {
|
|
|
|
- return "Invalid XPath. Details:\n" + err.message;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const nodeToString = function(node) {
|
|
|
|
- return node.toString();
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- return nodes.map(nodeToString).join(delimiter);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- JPATH_INITIAL: "",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- JPATH_DELIMITER: "\\n",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * JPath expression operation.
|
|
|
|
- *
|
|
|
|
- * @author Matt C (matt@artemisbot.uk)
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runJpath: function(input, args) {
|
|
|
|
- let query = args[0],
|
|
|
|
- delimiter = args[1],
|
|
|
|
- results,
|
|
|
|
- obj;
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- obj = JSON.parse(input);
|
|
|
|
- } catch (err) {
|
|
|
|
- return "Invalid input JSON: " + err.message;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- results = jpath.query(obj, query);
|
|
|
|
- } catch (err) {
|
|
|
|
- return "Invalid JPath expression: " + err.message;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return results.map(result => JSON.stringify(result)).join(delimiter);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- CSS_SELECTOR_INITIAL: "",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @constant
|
|
|
|
- * @default
|
|
|
|
- */
|
|
|
|
- CSS_QUERY_DELIMITER: "\\n",
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * CSS selector operation.
|
|
|
|
- *
|
|
|
|
- * @author Mikescher (https://github.com/Mikescher | https://mikescher.com)
|
|
|
|
- * @author n1474335 [n1474335@gmail.com]
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runCSSQuery: function(input, args) {
|
|
|
|
- let query = args[0],
|
|
|
|
- delimiter = args[1],
|
|
|
|
- parser = new DOMParser(),
|
|
|
|
- dom,
|
|
|
|
- result;
|
|
|
|
-
|
|
|
|
- if (!query.length || !input.length) {
|
|
|
|
- return "";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- dom = parser.parseFromString(input);
|
|
|
|
- } catch (err) {
|
|
|
|
- return "Invalid input HTML.";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try {
|
|
|
|
- const matcher = nwmatcher({document: dom});
|
|
|
|
- result = matcher.select(query, dom);
|
|
|
|
- } catch (err) {
|
|
|
|
- return "Invalid CSS Selector. Details:\n" + err.message;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const nodeToString = function(node) {
|
|
|
|
- return node.toString();
|
|
|
|
- /* xmldom does not return the outerHTML value.
|
|
|
|
- switch (node.nodeType) {
|
|
|
|
- case node.ELEMENT_NODE: return node.outerHTML;
|
|
|
|
- case node.ATTRIBUTE_NODE: return node.value;
|
|
|
|
- case node.TEXT_NODE: return node.wholeText;
|
|
|
|
- case node.COMMENT_NODE: return node.data;
|
|
|
|
- case node.DOCUMENT_NODE: return node.outerHTML;
|
|
|
|
- default: throw new Error("Unknown Node Type: " + node.nodeType);
|
|
|
|
- }*/
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- return result
|
|
|
|
- .map(nodeToString)
|
|
|
|
- .join(delimiter);
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * This tries to rename variable names in a code snippet according to a function.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {function} replacer - this function will be fed the token which should be renamed.
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- _replaceVariableNames(input, replacer) {
|
|
|
|
- const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig;
|
|
|
|
-
|
|
|
|
- return input.replace(tokenRegex, (...args) => {
|
|
|
|
- let match = args[0],
|
|
|
|
- quotes = args[1];
|
|
|
|
-
|
|
|
|
- if (!quotes) {
|
|
|
|
- return match;
|
|
|
|
- } else {
|
|
|
|
- return replacer(match);
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * To Snake Case operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runToSnakeCase(input, args) {
|
|
|
|
- const smart = args[0];
|
|
|
|
-
|
|
|
|
- if (smart) {
|
|
|
|
- return Code._replaceVariableNames(input, snakeCase);
|
|
|
|
- } else {
|
|
|
|
- return snakeCase(input);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * To Camel Case operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runToCamelCase(input, args) {
|
|
|
|
- const smart = args[0];
|
|
|
|
-
|
|
|
|
- if (smart) {
|
|
|
|
- return Code._replaceVariableNames(input, camelCase);
|
|
|
|
- } else {
|
|
|
|
- return camelCase(input);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * To Kebab Case operation.
|
|
|
|
- *
|
|
|
|
- * @param {string} input
|
|
|
|
- * @param {Object[]} args
|
|
|
|
- * @returns {string}
|
|
|
|
- */
|
|
|
|
- runToKebabCase(input, args) {
|
|
|
|
- const smart = args[0];
|
|
|
|
-
|
|
|
|
- if (smart) {
|
|
|
|
- return Code._replaceVariableNames(input, kebabCase);
|
|
|
|
- } else {
|
|
|
|
- return kebabCase(input);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-export default Code;
|
|
|