├── .nvmrc ├── .unibeautifyignore ├── test ├── fixtures │ └── test1.js ├── index.spec.ts ├── .unibeautifyrc.yml ├── __snapshots__ │ └── utils.spec.ts.snap ├── utils.spec.ts ├── mockStreams.ts └── commands │ ├── __snapshots__ │ ├── BeautifyCommand.spec.ts.snap │ └── SupportCommand.spec.ts.snap │ ├── SupportCommand.spec.ts │ └── BeautifyCommand.spec.ts ├── .npmignore ├── renovate.json ├── tsconfig.json ├── __mocks__ └── g-search.js ├── .gitignore ├── jest.config.js ├── .unibeautifyrc.yml ├── CHANGELOG.md ├── src ├── commands │ ├── BaseCommand.ts │ ├── SupportCommand.ts │ └── BeautifyCommand.ts ├── utils.ts └── cli.ts ├── .travis.yml ├── .codeclimate.yml ├── LICENSE ├── tslint.json ├── .vscode └── launch.json ├── package.json └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 9.11.2 2 | -------------------------------------------------------------------------------- /.unibeautifyignore: -------------------------------------------------------------------------------- 1 | test/fixtures/**/* 2 | -------------------------------------------------------------------------------- /test/fixtures/test1.js: -------------------------------------------------------------------------------- 1 | const test = 'test'; 2 | -------------------------------------------------------------------------------- /test/index.spec.ts: -------------------------------------------------------------------------------- 1 | test("sanity", () => { 2 | expect(true).toBe(true); 3 | }); 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !dist/**/*.js 3 | !dist/**/*.js.map 4 | !dist/**/*.d.ts 5 | !dist/**/*.json -------------------------------------------------------------------------------- /test/.unibeautifyrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | JavaScript: 3 | beautifiers: ["ESLint"] 4 | quotes: "double" -------------------------------------------------------------------------------- /test/__snapshots__/utils.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`findInstalledBeautifiers 1`] = ` 4 | Array [ 5 | "@unibeautify/beautifier-eslint", 6 | ] 7 | `; 8 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "devDependencies": { 6 | "automerge": true, 7 | "automergeType": "branch", 8 | "major": { 9 | "automerge": false 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { findInstalledBeautifiers } from "../src/utils"; 2 | 3 | test("findInstalledBeautifiers", () => { 4 | expect.assertions(2); 5 | return findInstalledBeautifiers().then(beautifierNames => { 6 | expect(beautifierNames).toHaveLength(1); 7 | expect(beautifierNames).toMatchSnapshot(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitAny": true, 5 | "removeComments": false, 6 | "noUnusedLocals": true, 7 | "strictNullChecks": true, 8 | "preserveConstEnums": true, 9 | "sourceMap": true, 10 | "target": "ES6", 11 | "declaration": true, 12 | "moduleResolution": "node", 13 | "outDir": "dist", 14 | "rootDir": "./src" 15 | }, 16 | "include": [ 17 | "./src/**/*.ts" 18 | ], 19 | "exclude": [ 20 | "./node_modules" 21 | ] 22 | } -------------------------------------------------------------------------------- /__mocks__/g-search.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const pkg = require(path.resolve(__dirname, "../package.json")); 3 | const { devDependencies } = pkg; 4 | 5 | const globalModules = fakeGlobalModules(); 6 | 7 | module.exports = function() { 8 | return Promise.resolve(globalModules); 9 | }; 10 | 11 | function fakeGlobalModules() { 12 | return Object.keys(devDependencies) 13 | .map(getModuleDetails) 14 | .filter(Boolean); 15 | } 16 | 17 | function getModuleDetails(moduleName) { 18 | try { 19 | const pkgPath = require.resolve(moduleName); 20 | const pkg = require(`${moduleName}/package.json`); 21 | return { name: pkg.name, version: pkg.version, location: pkgPath }; 22 | } catch (error) { 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project 2 | docs 3 | dist 4 | 5 | ### https://raw.github.com/github/gitignore/77e29837cf03b59fc4d885ea011bbd683caaaf85/node.gitignore 6 | 7 | # Logs 8 | logs 9 | *.log 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directory 32 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 33 | node_modules 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/mockStreams.ts: -------------------------------------------------------------------------------- 1 | import { Writable, Readable } from "stream"; 2 | 3 | export function createMockWritableStream(): MockWritableStream { 4 | const ws: Writable & { rawData: string } = new Writable() as any; 5 | ws.rawData = ""; 6 | ws._write = function(chunk: string, enc: string, next: Function) { 7 | ws.rawData += chunk; 8 | next(); 9 | }; 10 | return ws as any; 11 | } 12 | 13 | export interface MockWritableStream extends NodeJS.WriteStream { 14 | rawData: string; 15 | } 16 | 17 | export function createMockReadableStream( 18 | rawData: string, 19 | isTTY: boolean = false 20 | ): NodeJS.ReadStream { 21 | const rs: any = new Readable(); 22 | rs.isTTY = isTTY; 23 | rs._read = function() { 24 | rs.emit("data", rawData); 25 | rs.emit("end"); 26 | }; 27 | return rs; 28 | } 29 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | rootDir: ".", 5 | testEnvironment: "node", 6 | setupFiles: [], 7 | transform: { 8 | "^.+\\.tsx?$": "ts-jest", 9 | }, 10 | testRegex: "test/.+\\.(test|spec)\\.ts$", 11 | testPathIgnorePatterns: [ 12 | "/__mocks__/", 13 | "/dist/", 14 | "/node_modules/", 15 | ], 16 | moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], 17 | collectCoverage: true, 18 | coverageReporters: ["json", "lcov", "text", "html"], 19 | coveragePathIgnorePatterns: [ 20 | "/__mocks__/", 21 | "/dist/", 22 | "/test/", 23 | "/node_modules/", 24 | ], 25 | globals: { 26 | "ts-jest": { 27 | tsConfig: "tsconfig.json", 28 | diagnostics: true, 29 | }, 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /.unibeautifyrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | TypeScript: 3 | beautifiers: ["Prettier"] 4 | align_assignments: false 5 | arrow_parens: "as-needed" 6 | break_chained_methods: true 7 | end_with_comma: true 8 | end_with_semicolon: true 9 | indent_char: " " 10 | indent_size: 2 11 | jsx_brackets: false 12 | multiline_ternary: true 13 | object_curly_spacing: true 14 | quotes: "double" 15 | space_after_anon_function: false 16 | wrap_line_length: 80 17 | JavaScript: 18 | beautifiers: ["Prettier"] 19 | align_assignments: false 20 | arrow_parens: "as-needed" 21 | break_chained_methods: true 22 | end_with_comma: true 23 | end_with_semicolon: true 24 | indent_char: " " 25 | indent_size: 2 26 | jsx_brackets: false 27 | multiline_ternary: true 28 | object_curly_spacing: true 29 | quotes: "double" 30 | space_after_anon_function: false 31 | wrap_line_length: 80 32 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v0.5.1 (2018-12-13) 2 | - Fix for `--help` command not running properly [#121](https://github.com/Unibeautify/cli/issues/121) 3 | 4 | # v0.5.0 (2018-12-11) 5 | - Beautified results can now update file contents directly [#55](https://github.com/Unibeautify/cli/pull/55) 6 | - Color text will only be output if stdout is a terminal [#97](https://github.com/Unibeautify/cli/pull/97) 7 | - A language will be suggested if the specified one via `-l` isn't found [#116](https://github.com/Unibeautify/cli/pull/116) 8 | 9 | # v0.4.0 (2018-07-25) 10 | - Pass a Unibeautify configuration file into CLI options 11 | - Beautify text directly from files and output to stdout 12 | - Major refactoring [#49](https://github.com/Unibeautify/cli/issues/49) 13 | - More unit test coverage 14 | 15 | # v0.3.0 (2018-07-18) 16 | - Read text from stdin and output beautified results 17 | - Pass a configuration file or directly enter JSON into terminal to specify options -------------------------------------------------------------------------------- /src/commands/BaseCommand.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | 3 | export abstract class BaseCommand { 4 | protected stdout: NodeJS.WriteStream = process.stdout; 5 | protected stderr: NodeJS.WriteStream = process.stderr; 6 | 7 | protected writeOut(text: string): void { 8 | this.stdout.write(text + "\n"); 9 | } 10 | 11 | protected writeOutHeading(text: string): void { 12 | this.writeOut(this.stdout.isTTY ? chalk.blue(text) : text); 13 | } 14 | 15 | protected writeError(text: string): void { 16 | this.stderr.write((this.stderr.isTTY ? chalk.red(text) : text) + "\n"); 17 | } 18 | 19 | protected set exitCode(exitCode: number) { 20 | process.exitCode = exitCode; 21 | } 22 | 23 | protected get exitCode(): number { 24 | return process.exitCode || 0; 25 | } 26 | 27 | protected handleError(error: Error, exitCode: number): Promise { 28 | this.writeError(error.message); 29 | this.exitCode = exitCode; 30 | return Promise.reject(error); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | - CC_TEST_REPORTER_ID=0f88c4c7f8deeb56cc6bfc87c3d11d28f45e5a07dee8fb29a97cd66af1c89bf4 4 | language: node_js 5 | node_js: 6 | - "8" 7 | - "10" 8 | os: 9 | - linux 10 | - osx 11 | cache: 12 | directories: 13 | - node_modules # NPM packages 14 | before_script: 15 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 16 | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter; 17 | elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 18 | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-darwin-amd64 > ./cc-test-reporter; 19 | else 20 | echo Error:TRAVIS_OS_NAME && exit 1; 21 | fi 22 | - chmod +x ./cc-test-reporter 23 | - ./cc-test-reporter before-build 24 | script: 25 | - npm install -g unibeautify @unibeautify/beautifier-eslint eslint@4 26 | - npm run lint 27 | - npm run build 28 | - npm test 29 | after_script: 30 | - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT 31 | notifications: 32 | email: 33 | on_success: never 34 | on_failure: change 35 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | checks: 3 | argument-count: 4 | enabled: true 5 | config: 6 | threshold: 3 7 | complex-logic: 8 | enabled: true 9 | config: 10 | threshold: 4 11 | file-lines: 12 | enabled: false 13 | config: 14 | threshold: 250 15 | method-complexity: 16 | enabled: true 17 | config: 18 | threshold: 5 19 | method-count: 20 | enabled: true 21 | config: 22 | threshold: 20 23 | method-lines: 24 | enabled: true 25 | config: 26 | threshold: 50 27 | nested-control-flow: 28 | enabled: true 29 | config: 30 | threshold: 4 31 | return-statements: 32 | enabled: true 33 | config: 34 | threshold: 4 35 | similar-code: 36 | enabled: true 37 | config: 38 | threshold: #language-specific defaults. overrides affect all languages. 39 | identical-code: 40 | enabled: true 41 | config: 42 | threshold: #language-specific defaults. overrides affect all languages. 43 | exclude_patterns: 44 | - "dist/" 45 | - "**/node_modules/" 46 | - "/test/" 47 | - "**/*.d.ts" 48 | plugins: 49 | fixme: 50 | enabled: true -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Glavin Wiechert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": [ 4 | true, 5 | "log" 6 | ], 7 | "class-name": true, 8 | "comment-format": [ 9 | true, 10 | "check-space" 11 | ], 12 | "indent": [ 13 | true, 14 | "spaces" 15 | ], 16 | "no-duplicate-variable": true, 17 | "no-eval": true, 18 | "no-internal-module": true, 19 | "no-trailing-whitespace": true, 20 | "no-unsafe-finally": true, 21 | "no-var-keyword": true, 22 | "one-line": [ 23 | true, 24 | "check-open-brace", 25 | "check-whitespace" 26 | ], 27 | "quotemark": [ 28 | true, 29 | "double" 30 | ], 31 | "semicolon": [ 32 | true, 33 | "always" 34 | ], 35 | "triple-equals": [ 36 | true, 37 | "allow-null-check" 38 | ], 39 | "typedef-whitespace": [ 40 | true, 41 | { 42 | "call-signature": "nospace", 43 | "index-signature": "nospace", 44 | "parameter": "nospace", 45 | "property-declaration": "nospace", 46 | "variable-declaration": "nospace" 47 | } 48 | ], 49 | "variable-name": [ 50 | true, 51 | "ban-keywords" 52 | ], 53 | "whitespace": [ 54 | true, 55 | "check-branch", 56 | "check-decl", 57 | "check-operator", 58 | "check-separator", 59 | "check-type" 60 | ], 61 | "object-literal-sort-keys": true 62 | } 63 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Debug All Tests", 11 | "runtimeVersion": "9.10.1", 12 | "program": "${workspaceRoot}/node_modules/jest/bin/jest.js", 13 | "args": [ 14 | "--config", "jest.config.js", "--runInBand", "--coverage", "false" 15 | ], 16 | "runtimeArgs": ["--nolazy"], 17 | "console": "internalConsole", 18 | "env": { 19 | "NODE_ENV": "test" 20 | }, 21 | "protocol": "inspector", 22 | "sourceMaps": true, 23 | "outFiles": ["${workspaceRoot}/dist/"] 24 | }, 25 | { 26 | "type": "node", 27 | "request": "launch", 28 | "name": "Debug Current Tests File", 29 | "runtimeVersion": "9.10.1", 30 | "program": "${workspaceRoot}/node_modules/jest/bin/jest.js", 31 | "args": [ 32 | "--config", 33 | "jest.config.js", 34 | "--runInBand", 35 | "--coverage", 36 | "false", 37 | "${fileBasename}" 38 | ], 39 | "runtimeArgs": ["--nolazy"], 40 | "console": "internalConsole", 41 | "env": { 42 | "NODE_ENV": "test" 43 | }, 44 | "protocol": "inspector", 45 | "sourceMaps": true, 46 | "outFiles": ["${workspaceRoot}/dist/"] 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /src/commands/SupportCommand.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getSupportedLanguages, 3 | findInstalledBeautifiers, 4 | setupUnibeautify, 5 | getAllLanguages, 6 | } from "../utils"; 7 | import { BaseCommand } from "./BaseCommand"; 8 | 9 | export class SupportCommand extends BaseCommand { 10 | public support(options: { 11 | json?: boolean; 12 | languages?: boolean; 13 | beautifiers?: boolean; 14 | all?: boolean; 15 | }): Promise { 16 | const printer: (info: SupportInfo) => void = options.json 17 | ? this.jsonPrinter 18 | : this.listPrinter; 19 | const info: SupportInfo = {}; 20 | return setupUnibeautify().then(async unibeautify => { 21 | if (options.languages) { 22 | if (options.all) { 23 | info["languages"] = getAllLanguages(); 24 | } else { 25 | info["languages"] = getSupportedLanguages(); 26 | } 27 | } 28 | if (options.beautifiers) { 29 | const beautifiers = await findInstalledBeautifiers(); 30 | info["beautifiers"] = beautifiers; 31 | } 32 | if (Object.keys(info).length === 0) { 33 | this.writeError("Nothing to show"); 34 | // this.exit(1); 35 | this.exitCode = 1; 36 | } else { 37 | printer(info); 38 | // this.exit(0); 39 | } 40 | }); 41 | } 42 | 43 | private jsonPrinter = (info: SupportInfo) => { 44 | this.writeOut(JSON.stringify(info, null, 2)); 45 | // unibeautify:ignore-next-line 46 | } 47 | 48 | private listPrinter = (info: SupportInfo) => { 49 | Object.keys(info).forEach(section => { 50 | this.writeOutHeading(`Supported ${section}`); 51 | const items = info[section]; 52 | items.forEach((item, index) => this.writeOut(`${index + 1}. ${item}`)); 53 | }); 54 | // unibeautify:ignore-next-line 55 | } 56 | } 57 | 58 | interface SupportInfo { 59 | [section: string]: string[]; 60 | } 61 | -------------------------------------------------------------------------------- /test/commands/__snapshots__/BeautifyCommand.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`BeautifyCommand Beautify should beautify using options in config file 1`] = ` 4 | Object { 5 | "exitCode": 0, 6 | "stderr": "", 7 | "stdout": "const test = \\"test\\"; 8 | 9 | ", 10 | } 11 | `; 12 | 13 | exports[`BeautifyCommand Beautify should beautify using options passed in cmd 1`] = ` 14 | Object { 15 | "exitCode": 0, 16 | "stderr": "", 17 | "stdout": "const test = \\"test\\"; 18 | 19 | ", 20 | } 21 | `; 22 | 23 | exports[`BeautifyCommand Beautify should find config file without specifying it 1`] = ` 24 | Object { 25 | "exitCode": 0, 26 | "stderr": "", 27 | "stdout": "const test = \\"test\\"; 28 | 29 | ", 30 | } 31 | `; 32 | 33 | exports[`BeautifyCommand Errors should throw an error saying cannot find language: json 1`] = ` 34 | Object { 35 | "exitCode": 1, 36 | "stderr": "Cannot find language. 37 | ", 38 | "stdout": "", 39 | } 40 | `; 41 | 42 | exports[`BeautifyCommand Errors should throw an error saying language is required: json 1`] = ` 43 | Object { 44 | "exitCode": 1, 45 | "stderr": "A language is required. 46 | ", 47 | "stdout": "", 48 | } 49 | `; 50 | 51 | exports[`BeautifyCommand Errors should throw an error suggesting C, D and E for language: json 1`] = ` 52 | Object { 53 | "exitCode": 1, 54 | "stderr": "Language 'a' was not found. Did you mean: 55 | - C 56 | - D 57 | - E 58 | ", 59 | "stdout": "", 60 | } 61 | `; 62 | 63 | exports[`BeautifyCommand Errors should throw an error suggesting JavaScript for language: json 1`] = ` 64 | Object { 65 | "exitCode": 1, 66 | "stderr": "Language 'javascript' was not found. Did you mean: 67 | - JavaScript 68 | ", 69 | "stdout": "", 70 | } 71 | `; 72 | 73 | exports[`BeautifyCommand Errors should throw an error with invalid json: json 1`] = ` 74 | Object { 75 | "exitCode": 2, 76 | "stderr": "Unexpected end of JSON input 77 | ", 78 | "stdout": "", 79 | } 80 | `; 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@unibeautify/cli", 3 | "version": "0.5.1", 4 | "description": "CLI for Unibeautify", 5 | "main": "dist/index.js", 6 | "bin": { 7 | "unibeautify": "dist/cli.js" 8 | }, 9 | "scripts": { 10 | "compile": "tsc", 11 | "clean": "rimraf dist", 12 | "jest": "jest --verbose", 13 | "test": "npm-run-all build jest", 14 | "docs": "typedoc --out docs --includeDeclarations", 15 | "prepare": "npm run build", 16 | "build": "npm-run-all clean compile", 17 | "lint:src": "tslint src/**/*.ts", 18 | "lint": "npm-run-all clean compile lint:*" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/Unibeautify/cli.git" 23 | }, 24 | "keywords": [ 25 | "cli-app", 26 | "cli", 27 | "unibeautify", 28 | "beautify", 29 | "beautifier", 30 | "formatter", 31 | "format", 32 | "pretty" 33 | ], 34 | "author": { 35 | "name": "Glavin Wiechert", 36 | "email": "glavin.wiechert@gmail.com", 37 | "url": "https://github.com/glavin001" 38 | }, 39 | "license": "MIT", 40 | "bugs": { 41 | "url": "https://github.com/Unibeautify/cli/issues" 42 | }, 43 | "homepage": "https://github.com/Unibeautify/cli#readme", 44 | "engines": { 45 | "node": ">=6.0.0" 46 | }, 47 | "devDependencies": { 48 | "@types/cosmiconfig": "5.0.3", 49 | "@types/fast-levenshtein": "0.0.1", 50 | "@types/jest": "24.9.1", 51 | "@types/yargs": "13.0.4", 52 | "@unibeautify/beautifier-eslint": "0.6.0", 53 | "eslint": "5.16.0", 54 | "jest": "24.9.0", 55 | "npm-run-all": "4.1.5", 56 | "rimraf": "3.0.2", 57 | "ts-jest": "24.3.0", 58 | "tslint": "5.20.1", 59 | "typedoc": "0.17.8", 60 | "typescript": "3.5.3" 61 | }, 62 | "dependencies": { 63 | "chalk": "^2.4.1", 64 | "cosmiconfig": "^5.0.7", 65 | "fast-levenshtein": "^2.0.6", 66 | "g-search": "^0.3.0", 67 | "requireg": "^0.2.1", 68 | "unibeautify": "^0.17.0", 69 | "yargs": "^14.0.0" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import unibeautify, { Unibeautify } from "unibeautify"; 2 | const requireg = require("requireg"); 3 | const gSearch = require("g-search"); 4 | 5 | /** 6 | Find all globally installed beautifiers. 7 | */ 8 | export function findInstalledBeautifiers(): Promise { 9 | return new Promise((resolve, reject) => { 10 | gSearch() 11 | .then((globalPackages: GlobalSearchResult[]) => { 12 | const packageNames = globalPackages.map(pkg => pkg.name); 13 | const beautifierNames = packageNames.filter(isBeautifierPackageName); 14 | return resolve(beautifierNames); 15 | }) 16 | .catch((error: Error) => { 17 | return reject(error); 18 | }); 19 | }); 20 | } 21 | 22 | export function isBeautifierPackageName(packageName: string): boolean { 23 | return /beautifier-.*/.test(packageName); 24 | } 25 | 26 | export function loadBeautifiers(beautifierNames: string[]): Unibeautify { 27 | const beautifiers = beautifierNames 28 | .map(beautifierName => { 29 | try { 30 | return requireg(beautifierName).default; 31 | } catch (error) { 32 | console.error(error); 33 | return null; 34 | } 35 | }) 36 | .filter(Boolean); 37 | return unibeautify.loadBeautifiers(beautifiers); 38 | } 39 | 40 | export function loadInstalledBeautifiers(): Promise { 41 | return findInstalledBeautifiers().then((beautifierNames: string[]) => { 42 | return loadBeautifiers(beautifierNames); 43 | }); 44 | } 45 | 46 | export function setupUnibeautify(): Promise { 47 | return loadInstalledBeautifiers(); 48 | } 49 | 50 | export function getSupportedLanguages(): string[] { 51 | return unibeautify.supportedLanguages.map(language => { 52 | return language.name; 53 | }); 54 | } 55 | 56 | export function getAllLanguages(): string[] { 57 | return unibeautify.getLoadedLanguages().map(language => { 58 | return language.name; 59 | }); 60 | } 61 | 62 | export interface GlobalSearchResult { 63 | name: string; 64 | version: string; 65 | location: string; 66 | } 67 | -------------------------------------------------------------------------------- /test/commands/SupportCommand.spec.ts: -------------------------------------------------------------------------------- 1 | import { SupportCommand } from "../../src/commands/SupportCommand"; 2 | import { createMockWritableStream } from "../mockStreams"; 3 | 4 | describe("SupportCommand", () => { 5 | class CustomCommand extends SupportCommand { 6 | protected stdout = createMockWritableStream(); 7 | protected stderr = createMockWritableStream(); 8 | protected readFromStdin() { 9 | return Promise.resolve(""); 10 | } 11 | public toJSON(): object { 12 | return { 13 | exitCode: this.exitCode, 14 | stderr: this.stderr.rawData, 15 | stdout: this.stdout.rawData, 16 | }; 17 | } 18 | } 19 | describe("Support", () => { 20 | describe("with JSON", async () => { 21 | test("languages", async () => { 22 | const command = new CustomCommand(); 23 | await command.support({ 24 | all: true, 25 | json: true, 26 | languages: true, 27 | }); 28 | expect(command.toJSON()).toMatchSnapshot(); 29 | }); 30 | }); 31 | describe("without JSON", async () => { 32 | test("languages", async () => { 33 | const command = new CustomCommand(); 34 | await command.support({ 35 | all: true, 36 | json: false, 37 | languages: true, 38 | }); 39 | expect(command.toJSON()).toMatchSnapshot(); 40 | }); 41 | test("supported languages", async () => { 42 | const command = new CustomCommand(); 43 | await command.support({ 44 | all: false, 45 | json: false, 46 | languages: true, 47 | }); 48 | expect(command.toJSON()).toMatchSnapshot(); 49 | }); 50 | test("installed beautifiers", async () => { 51 | const command = new CustomCommand(); 52 | await command.support({ 53 | all: false, 54 | beautifiers: true, 55 | json: false, 56 | }); 57 | expect(command.toJSON()).toMatchSnapshot(); 58 | }); 59 | }); 60 | test("should exit with message 'nothing to show'", async () => { 61 | const command = new CustomCommand(); 62 | await command.support({ 63 | all: false, 64 | beautifiers: false, 65 | json: false, 66 | languages: false, 67 | }); 68 | expect(command.toJSON()).toMatchSnapshot(); 69 | }); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | import * as program from "yargs"; 7 | 8 | import { BeautifyCommand } from "./commands/BeautifyCommand"; 9 | import { SupportCommand } from "./commands/SupportCommand"; 10 | 11 | program 12 | .version() 13 | .command({ 14 | builder: { 15 | "config-file": { 16 | alias: "c", 17 | demandOption: false, 18 | describe: "Beautifier configuration file", 19 | type: "string", 20 | }, 21 | "config-json": { 22 | demandOption: false, 23 | describe: "Beautifier configuration as stringified JSON", 24 | type: "string", 25 | }, 26 | "file-path": { 27 | alias: "f", 28 | demandOption: false, 29 | describe: "Path of the file to beautify from stdin", 30 | type: "string", 31 | }, 32 | inplace: { 33 | alias: "i", 34 | default: false, 35 | demandOption: false, 36 | describe: "Replace file(s) with beautified results", 37 | type: "boolean", 38 | }, 39 | language: { 40 | alias: "l", 41 | demandOption: true, 42 | describe: "Language of file to beautify", 43 | type: "string", 44 | }, 45 | "out-file": { 46 | alias: "o", 47 | demandOption: false, 48 | describe: "Output file of beautified results", 49 | type: "string", 50 | }, 51 | }, 52 | command: "*", 53 | describe: "Beautify Files", 54 | handler: (argv: any) => { 55 | const main = new BeautifyCommand(); 56 | main.beautify(argv).catch((error: Error) => {}); 57 | }, 58 | }) 59 | .command({ 60 | aliases: ["list", "ls"], 61 | builder: { 62 | all: { 63 | alias: "a", 64 | default: false, 65 | demandOption: false, 66 | describe: "List all languages supported", 67 | }, 68 | beautifiers: { 69 | alias: "b", 70 | default: false, 71 | demandOption: false, 72 | describe: "List installed beautifiers", 73 | }, 74 | json: { 75 | alias: "j", 76 | default: false, 77 | demandOption: false, 78 | describe: "List as JSON array", 79 | }, 80 | languages: { 81 | alias: "l", 82 | default: false, 83 | demandOption: false, 84 | describe: "List supported languages based on installed beautifiers", 85 | }, 86 | }, 87 | command: "support", 88 | describe: "List languages and beautifiers", 89 | handler: (argv: any) => { 90 | const main = new SupportCommand(); 91 | main.support(argv).catch((error: Error) => {}); 92 | }, 93 | }) 94 | .help().argv; 95 | 96 | // .option("-i, --input-file [file]", "Input file to be beautified") 97 | // .option("-b, --beautifiers [beautifier...]", "Installed Beautifiers to load") 98 | // .option("--input-dir [directory]", "Input directory of files to be beautified") 99 | // .option("--output-dir [directory]", "Output directory of beautified results") 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unibeautify-CLI 2 | 3 | [![Build Status](https://travis-ci.com/Unibeautify/cli.svg?branch=master)](https://travis-ci.com/Unibeautify/cli) [![Maintainability](https://api.codeclimate.com/v1/badges/722b515b28d1bb71b6c7/maintainability)](https://codeclimate.com/github/Unibeautify/cli/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/722b515b28d1bb71b6c7/test_coverage)](https://codeclimate.com/github/Unibeautify/cli/test_coverage) 4 | 5 | > CLI for [Unibeautify](https://github.com/Unibeautify/unibeautify) 6 | 7 | ## Installation 8 | 9 | ```bash 10 | $ npm install --global @unibeautify/cli 11 | ``` 12 | 13 | ## Usage 14 | 15 | The package will be globally accessible as a new command-line interface (CLI) application called [`unibeautify`](https://github.com/Unibeautify/unibeautify). 16 | 17 | ### Help 18 | 19 | **Note**: Not all options are currently supported. 20 | 21 | ```bash 22 | $ unibeautify --help 23 | 24 | unibeautify 25 | 26 | Beautify Files 27 | 28 | Commands: 29 | unibeautify Beautify Files [default] 30 | unibeautify support List languages and beautifiers [aliases: list, ls] 31 | 32 | Options: 33 | --version Show version number [boolean] 34 | --help Show help [boolean] 35 | --config-file, -c Beautifier configuration file [string] 36 | --config-json Beautifier configuration as stringified JSON [string] 37 | --file-path, -f Path of the file to beautify from stdin [string] 38 | --inplace, -i Replace file(s) with beautified results [boolean] [default: false] 39 | --language, -l Language of file to beautify [string] [required] 40 | --out-file, -o Output file of beautified results [string] 41 | 42 | ``` 43 | ```bash 44 | $ unibeautify list --help 45 | 46 | unibeautify support 47 | 48 | List languages and beautifiers 49 | 50 | Options: 51 | --version Show version number [boolean] 52 | --help Show help [boolean] 53 | --all, -a List all languages supported [default: false] 54 | --beautifiers, -b List installed beautifiers [default: false] 55 | --json, -j List as JSON array [default: false] 56 | --languages, -l List supported languages based on installed beautifiers [default: false] 57 | ``` 58 | 59 | ### Example 60 | 61 | Install [`unibeautify`](https://github.com/Unibeautify/unibeautify) and a Beautifier, such as [`beautifier-prettydiff`](https://github.com/Unibeautify/beautifier-prettydiff): 62 | 63 | ``` 64 | $ npm install --global unibeautify @unibeautify/beautifier-prettydiff 65 | ``` 66 | 67 | Then beautify using a language that Beautifier supports: 68 | 69 | ```bash 70 | $ unibeautify --language JavaScript --config-json '{"JavaScript": {"beautifiers": ["ESLint"],"quotes": "double"}}' <<< "const test = 'test';" 71 | ``` 72 | 73 | This returns the following formatted result: 74 | 75 | ```javascript 76 | const test = "test"; 77 | ``` 78 | -------------------------------------------------------------------------------- /src/commands/BeautifyCommand.ts: -------------------------------------------------------------------------------- 1 | import { BeautifyData, Unibeautify } from "unibeautify"; 2 | import * as cosmiconfig from "cosmiconfig"; 3 | import * as fs from "fs"; 4 | import * as levenshtein from "fast-levenshtein"; 5 | 6 | import { setupUnibeautify, getAllLanguages } from "../utils"; 7 | import { BaseCommand } from "./BaseCommand"; 8 | 9 | export class BeautifyCommand extends BaseCommand { 10 | protected stdin: NodeJS.ReadStream = process.stdin; 11 | 12 | public beautify(programArgs: IArgs): Promise { 13 | const { language, filePath } = programArgs; 14 | return setupUnibeautify().then(unibeautify => { 15 | return this.validateLanguage(language, unibeautify).then(() => { 16 | return Promise.all([ 17 | this.readConfig(programArgs), 18 | this.readText(filePath), 19 | ]).then(([config, text]) => { 20 | const data: BeautifyData = { 21 | filePath: filePath, 22 | languageName: language, 23 | options: (config as any) || {}, 24 | text, 25 | }; 26 | return unibeautify 27 | .beautify(data) 28 | .then((result: string) => { 29 | return this.writeToFileOrStdout({ result, programArgs }).then( 30 | () => result 31 | ); 32 | }) 33 | .catch((error: Error) => { 34 | return this.handleError(error, 1); 35 | }); 36 | }); 37 | }); 38 | }); 39 | } 40 | 41 | private readConfig(programArgs: IArgs): Promise { 42 | const { configFile, configJson, filePath } = programArgs; 43 | if (configJson) { 44 | return this.parseConfig(configJson); 45 | } else { 46 | return this.configFile({ configFile, filePath }); 47 | } 48 | } 49 | 50 | private readText(filePath?: string): Promise { 51 | if (filePath) { 52 | return this.readFile(filePath); 53 | } else { 54 | return this.readFromStdin(); 55 | } 56 | } 57 | 58 | private parseConfig(configJson: string): Promise { 59 | try { 60 | return Promise.resolve(JSON.parse(configJson)); 61 | } catch (error) { 62 | return this.handleError(error, 2); 63 | } 64 | } 65 | 66 | private configFile({ 67 | configFile, 68 | filePath, 69 | }: { 70 | configFile?: string; 71 | filePath?: string; 72 | }) { 73 | const configExplorer = cosmiconfig("unibeautify", { stopDir: filePath }); 74 | const loadConfigPromise = configFile 75 | ? configExplorer.load(configFile) 76 | : configExplorer.search(filePath); 77 | return loadConfigPromise 78 | .then(result => (result ? result.config : null)) 79 | .catch(error => 80 | Promise.reject( 81 | new Error(`Could not load configuration file ${configFile}`) 82 | ) 83 | ); 84 | } 85 | 86 | protected readFromStdin(): Promise { 87 | return new Promise((resolve, reject) => { 88 | let text = ""; 89 | if (this.stdin.isTTY) { 90 | resolve(text); 91 | return; 92 | } 93 | this.stdin.on("data", (data: string) => { 94 | text = data.toString(); 95 | }); 96 | this.stdin.on("end", () => { 97 | resolve(text); 98 | }); 99 | this.stdin.on("error", (err: any) => { 100 | if (err.code === "EPIPE") { 101 | return this.handleError(err, 1); 102 | } 103 | process.emit("warning", err); 104 | }); 105 | this.stdin.resume(); 106 | }); 107 | } 108 | 109 | private readFile(filePath: string): Promise { 110 | return new Promise((resolve, reject) => { 111 | fs.readFile(filePath, (error, data) => { 112 | if (error) { 113 | return reject(error); 114 | } 115 | return resolve(data.toString()); 116 | }); 117 | }); 118 | } 119 | 120 | private writeToFileOrStdout({ 121 | result, 122 | programArgs, 123 | }: { 124 | result: string; 125 | programArgs: IArgs; 126 | }) { 127 | const { inplace, filePath } = programArgs; 128 | if (inplace && filePath) { 129 | return this.writeFile(result, filePath); 130 | } else { 131 | return Promise.resolve(this.writeOut(result)); 132 | } 133 | } 134 | 135 | private writeFile(text: string, filePath: string): Promise { 136 | return new Promise((resolve, reject) => { 137 | fs.writeFile(filePath, text, error => { 138 | if (error) { 139 | return reject(error); 140 | } 141 | return resolve(); 142 | }); 143 | }); 144 | } 145 | 146 | private validateLanguage( 147 | language: string | undefined, 148 | unibeautify: Unibeautify 149 | ): Promise { 150 | if (!language) { 151 | const error = new Error("A language is required."); 152 | return this.handleError(error, 1); 153 | } 154 | const langs = unibeautify.findLanguages({ name: language }); 155 | if (langs.length === 0) { 156 | const allLanguages = getAllLanguages(); 157 | const distances: number[] = allLanguages.map(lang => 158 | levenshtein.get(lang.toLowerCase(), language.toLowerCase()) 159 | ); 160 | const bestDistance: number = Math.min(...distances); 161 | const distanceThreshold = 2; 162 | const bestMatchLanguages = allLanguages.filter( 163 | (lang, index) => 164 | distances[index] <= Math.min(distanceThreshold, bestDistance) 165 | ); 166 | if (bestMatchLanguages.length > 0) { 167 | const limit = 3; 168 | const error = new Error( 169 | `Language '${language}' was not found. Did you mean:\n${bestMatchLanguages 170 | .slice(0, limit) 171 | .map(lang => ` - ${lang}`) 172 | .join("\n")}` 173 | ); 174 | return this.handleError(error, 1); 175 | } 176 | } 177 | return Promise.resolve(); 178 | } 179 | } 180 | 181 | /** 182 | Arguments parsed for program. 183 | */ 184 | export interface IArgs { 185 | args: string[]; 186 | language?: string; 187 | outFile?: string; 188 | inplace?: boolean; 189 | configFile?: string; 190 | configJson?: string; 191 | filePath?: string; 192 | } 193 | -------------------------------------------------------------------------------- /test/commands/BeautifyCommand.spec.ts: -------------------------------------------------------------------------------- 1 | import { BeautifyCommand } from "../../src/commands/BeautifyCommand"; 2 | import { 3 | createMockWritableStream, 4 | createMockReadableStream, 5 | } from "../mockStreams"; 6 | import * as fs from "fs"; 7 | 8 | describe("BeautifyCommand", () => { 9 | class CustomCommand extends BeautifyCommand { 10 | constructor(private rawStdin: string = "", private isTTY: boolean = false) { 11 | super(); 12 | this.rawStdin; 13 | } 14 | protected stdin = createMockReadableStream(this.rawStdin, this.isTTY); 15 | protected stdout = createMockWritableStream(); 16 | protected stderr = createMockWritableStream(); 17 | public toJSON() { 18 | return { 19 | exitCode: this.exitCode, 20 | stderr: this.stderr.rawData, 21 | stdout: this.stdout.rawData, 22 | }; 23 | } 24 | } 25 | describe("Beautify", () => { 26 | test("should beautify using options passed in cmd", async () => { 27 | const command = new CustomCommand(); 28 | await command.beautify({ 29 | args: [], 30 | configJson: `{"JavaScript": {"beautifiers": ["ESLint"],"quotes": "double"}}`, 31 | filePath: "test/fixtures/test1.js", 32 | language: "JavaScript", 33 | }); 34 | const json = command.toJSON(); 35 | expect(json.exitCode).toBe(0); 36 | expect(json).toMatchSnapshot(); 37 | }); 38 | test("should beautify using options in config file", async () => { 39 | const command = new CustomCommand(); 40 | await command.beautify({ 41 | args: [], 42 | configFile: "test/.unibeautifyrc.yml", 43 | filePath: "test/fixtures/test1.js", 44 | language: "JavaScript", 45 | }); 46 | const json = command.toJSON(); 47 | expect(json.exitCode).toBe(0); 48 | expect(json).toMatchSnapshot(); 49 | }); 50 | test("should find config file without specifying it", async () => { 51 | const command = new CustomCommand(); 52 | await command.beautify({ 53 | args: [], 54 | filePath: "test/fixtures/test1.js", 55 | language: "JavaScript", 56 | }); 57 | const json = command.toJSON(); 58 | expect(json.exitCode).toBe(0); 59 | expect(json).toMatchSnapshot(); 60 | }); 61 | test("should beautify using stdin", async () => { 62 | const command = new CustomCommand("const test = 'test';"); 63 | return command 64 | .beautify({ 65 | args: [], 66 | configFile: "test/.unibeautifyrc.yml", 67 | language: "JavaScript", 68 | }) 69 | .then(() => { 70 | const json = command.toJSON(); 71 | expect(json.exitCode).toBe(0); 72 | expect(json.stderr).toBe(""); 73 | // tslint:disable-next-line:quotemark 74 | expect(json.stdout).toBe('const test = "test";\n'); 75 | }); 76 | }); 77 | test("should beautify using stdin with TTY", async () => { 78 | const command = new CustomCommand("const test = 'test';", true); 79 | return command 80 | .beautify({ 81 | args: [], 82 | configFile: "test/.unibeautifyrc.yml", 83 | language: "JavaScript", 84 | }) 85 | .then(() => { 86 | const json = command.toJSON(); 87 | expect(json.exitCode).toBe(0); 88 | expect(json.stderr).toBe(""); 89 | expect(json.stdout).toBe("\n"); 90 | }); 91 | }); 92 | test("should accept blank files or text", async () => { 93 | const command = new CustomCommand(); 94 | return command 95 | .beautify({ 96 | args: [], 97 | configFile: "test/.unibeautifyrc.yml", 98 | language: "JavaScript", 99 | }) 100 | .then(() => { 101 | const json = command.toJSON(); 102 | expect(json.exitCode).toBe(0); 103 | expect(json.stderr).toBe(""); 104 | // tslint:disable-next-line:quotemark 105 | expect(json.stdout).toBe("\n"); 106 | }); 107 | }); 108 | test("should beautify and write to file", async () => { 109 | const command = new CustomCommand("const test = 'test';"); 110 | const originPath = "test/fixtures/test1.js"; 111 | const destPath = "test/commands/test1.js"; 112 | return copyFile(originPath, destPath).then(() => { 113 | return command 114 | .beautify({ 115 | args: [], 116 | configFile: "test/.unibeautifyrc.yml", 117 | filePath: destPath, 118 | inplace: true, 119 | language: "JavaScript", 120 | }) 121 | .then(() => { 122 | return readFile(destPath).then(result => { 123 | const json = command.toJSON(); 124 | expect(json.exitCode).toBe(0); 125 | expect(json.stderr).toBe(""); 126 | // tslint:disable-next-line:quotemark 127 | expect(result.toString()).toBe('const test = "test";\n'); 128 | return unlink(destPath); 129 | }); 130 | }); 131 | }); 132 | }); 133 | }); 134 | describe("Errors", () => { 135 | test("should throw error when cannot find text file", () => { 136 | const command = new CustomCommand(); 137 | const thenCb = jest.fn(); 138 | const catchCb = jest.fn(); 139 | return command 140 | .beautify({ 141 | args: [], 142 | configFile: "test/.unibeautifyrc.yml", 143 | filePath: "test/test2.js", 144 | language: "JavaScript", 145 | }) 146 | .then(thenCb) 147 | .catch(catchCb) 148 | .then(() => { 149 | expect(thenCb).not.toBeCalled(); 150 | expect(catchCb).toHaveBeenCalled(); 151 | expect(catchCb.mock.calls).toHaveLength(1); 152 | expect(catchCb.mock.calls[0]).toHaveLength(1); 153 | expect((catchCb.mock.calls[0][0]).message).toBe( 154 | "ENOENT: no such file or directory, open 'test/test2.js'" 155 | ); 156 | }); 157 | }); 158 | test("should throw error when cannot find config", () => { 159 | const command = new CustomCommand(); 160 | const thenCb = jest.fn(); 161 | const catchCb = jest.fn(); 162 | const configFile = "test/.unibeautifyrc2.yml"; 163 | return command 164 | .beautify({ 165 | args: [], 166 | configFile, 167 | filePath: "test/fixtures/test1.js", 168 | language: "JavaScript", 169 | }) 170 | .then(thenCb) 171 | .catch(catchCb) 172 | .then(() => { 173 | expect(thenCb).not.toBeCalled(); 174 | expect(catchCb).toHaveBeenCalled(); 175 | expect(catchCb.mock.calls).toHaveLength(1); 176 | expect(catchCb.mock.calls[0]).toHaveLength(1); 177 | expect((catchCb.mock.calls[0][0]).message).toBe( 178 | `Could not load configuration file ${configFile}` 179 | ); 180 | }); 181 | }); 182 | test("should throw an error saying language is required", () => { 183 | const command = new CustomCommand(); 184 | const thenCb = jest.fn(); 185 | const catchCb = jest.fn(); 186 | return command 187 | .beautify({ 188 | args: [], 189 | configFile: "test/.unibeautifyrc.yml", 190 | filePath: "test/fixtures/test1.js", 191 | }) 192 | .then(thenCb) 193 | .catch(catchCb) 194 | .then(() => { 195 | expect(thenCb).not.toBeCalled(); 196 | expect(catchCb).toHaveBeenCalled(); 197 | expect(catchCb.mock.calls).toHaveLength(1); 198 | expect(catchCb.mock.calls[0]).toHaveLength(1); 199 | expect(catchCb).toHaveProperty( 200 | ["mock", "calls", 0, 0, "message"], 201 | "A language is required." 202 | ); 203 | const json = command.toJSON(); 204 | expect(json.exitCode).toBe(1); 205 | expect(json).toMatchSnapshot("json"); 206 | }); 207 | }); 208 | test("should throw an error saying cannot find language", () => { 209 | const command = new CustomCommand(); 210 | const thenCb = jest.fn(); 211 | const catchCb = jest.fn(); 212 | return command 213 | .beautify({ 214 | args: [], 215 | configFile: "test/.unibeautifyrc.yml", 216 | filePath: "test/fixtures/test1.js", 217 | language: "thisIsntALanguage", 218 | }) 219 | .then(thenCb) 220 | .catch(catchCb) 221 | .then(() => { 222 | expect(thenCb).not.toBeCalled(); 223 | expect(catchCb).toHaveBeenCalled(); 224 | expect(catchCb.mock.calls).toHaveLength(1); 225 | expect(catchCb.mock.calls[0]).toHaveLength(1); 226 | expect(catchCb).toHaveProperty( 227 | ["mock", "calls", 0, 0, "message"], 228 | "Cannot find language." 229 | ); 230 | const json = command.toJSON(); 231 | expect(json.exitCode).toBe(1); 232 | expect(json).toMatchSnapshot("json"); 233 | }); 234 | }); 235 | test("should throw an error suggesting JavaScript for language", () => { 236 | const command = new CustomCommand(); 237 | const thenCb = jest.fn(); 238 | const catchCb = jest.fn(); 239 | return command 240 | .beautify({ 241 | args: [], 242 | configFile: "test/.unibeautifyrc.yml", 243 | filePath: "test/fixtures/test1.js", 244 | language: "javascript", 245 | }) 246 | .then(thenCb) 247 | .catch(catchCb) 248 | .then(() => { 249 | expect(thenCb).not.toBeCalled(); 250 | expect(catchCb).toHaveBeenCalled(); 251 | expect(catchCb.mock.calls).toHaveLength(1); 252 | expect(catchCb.mock.calls[0]).toHaveLength(1); 253 | expect(catchCb).toHaveProperty( 254 | ["mock", "calls", 0, 0, "message"], 255 | "Language 'javascript' was not found. Did you mean:\n - JavaScript" 256 | ); 257 | const json = command.toJSON(); 258 | expect(json.exitCode).toBe(1); 259 | expect(json).toMatchSnapshot("json"); 260 | }); 261 | }); 262 | test("should throw an error suggesting C, D and E for language", () => { 263 | const command = new CustomCommand(); 264 | const thenCb = jest.fn(); 265 | const catchCb = jest.fn(); 266 | return command 267 | .beautify({ 268 | args: [], 269 | configFile: "test/.unibeautifyrc.yml", 270 | filePath: "test/fixtures/test1.js", 271 | language: "a", 272 | }) 273 | .then(thenCb) 274 | .catch(catchCb) 275 | .then(() => { 276 | expect(thenCb).not.toBeCalled(); 277 | expect(catchCb).toHaveBeenCalled(); 278 | expect(catchCb.mock.calls).toHaveLength(1); 279 | expect(catchCb.mock.calls[0]).toHaveLength(1); 280 | expect(catchCb).toHaveProperty( 281 | ["mock", "calls", 0, 0, "message"], 282 | "Language 'a' was not found. Did you mean:\n - C\n - D\n - E" 283 | ); 284 | const json = command.toJSON(); 285 | expect(json.exitCode).toBe(1); 286 | expect(json).toMatchSnapshot("json"); 287 | }); 288 | }); 289 | test("should throw an error with invalid json", () => { 290 | const command = new CustomCommand(); 291 | const thenCb = jest.fn(); 292 | const catchCb = jest.fn(); 293 | return command 294 | .beautify({ 295 | args: [], 296 | configJson: `{"JavaScript": {"beautifiers": ["ESLint"],"quotes": "double"`, 297 | filePath: "test/fixtures/test1.js", 298 | language: "JavaScript", 299 | }) 300 | .then(thenCb) 301 | .catch(catchCb) 302 | .then(() => { 303 | expect(thenCb).not.toBeCalled(); 304 | expect(catchCb).toHaveBeenCalled(); 305 | expect(catchCb.mock.calls).toHaveLength(1); 306 | expect(catchCb.mock.calls[0]).toHaveLength(1); 307 | expect(catchCb).toHaveProperty( 308 | ["mock", "calls", 0, 0, "message"], 309 | "Unexpected end of JSON input" 310 | ); 311 | const json = command.toJSON(); 312 | expect(json.exitCode).toBe(2); 313 | expect(json).toMatchSnapshot("json"); 314 | }); 315 | }); 316 | }); 317 | }); 318 | 319 | function copyFile(filePath: string, destPath: string): Promise { 320 | return new Promise((resolve, reject) => { 321 | fs.copyFile(filePath, destPath, error => { 322 | if (error) { 323 | return reject(error); 324 | } 325 | return resolve(); 326 | }); 327 | }); 328 | } 329 | 330 | function readFile(filePath: string): Promise { 331 | return new Promise((resolve, reject) => { 332 | fs.readFile(filePath, (error, data) => { 333 | if (error) { 334 | return reject(error); 335 | } 336 | return resolve(data.toString()); 337 | }); 338 | }); 339 | } 340 | 341 | function unlink(filePath: string): Promise { 342 | return new Promise((resolve, reject) => { 343 | fs.unlink(filePath, error => { 344 | if (error) { 345 | return reject(error); 346 | } 347 | return resolve(); 348 | }); 349 | }); 350 | } 351 | -------------------------------------------------------------------------------- /test/commands/__snapshots__/SupportCommand.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`SupportCommand Support should exit with message 'nothing to show' 1`] = ` 4 | Object { 5 | "exitCode": 1, 6 | "stderr": "Nothing to show 7 | ", 8 | "stdout": "", 9 | } 10 | `; 11 | 12 | exports[`SupportCommand Support with JSON languages 1`] = ` 13 | Object { 14 | "exitCode": 0, 15 | "stderr": "", 16 | "stdout": "{ 17 | \\"languages\\": [ 18 | \\"1C Enterprise\\", 19 | \\"ABAP\\", 20 | \\"ABNF\\", 21 | \\"AGS Script\\", 22 | \\"AMPL\\", 23 | \\"ANTLR\\", 24 | \\"API Blueprint\\", 25 | \\"APL\\", 26 | \\"ASN.1\\", 27 | \\"ASP\\", 28 | \\"ATS\\", 29 | \\"ActionScript\\", 30 | \\"Ada\\", 31 | \\"Adobe Font Metrics\\", 32 | \\"Agda\\", 33 | \\"Alloy\\", 34 | \\"Alpine Abuild\\", 35 | \\"AngelScript\\", 36 | \\"Ant Build System\\", 37 | \\"ApacheConf\\", 38 | \\"Apex\\", 39 | \\"Apollo Guidance Computer\\", 40 | \\"AppleScript\\", 41 | \\"Arc\\", 42 | \\"Arduino\\", 43 | \\"AsciiDoc\\", 44 | \\"AspectJ\\", 45 | \\"Assembly\\", 46 | \\"Augeas\\", 47 | \\"AutoHotkey\\", 48 | \\"AutoIt\\", 49 | \\"Awk\\", 50 | \\"Ballerina\\", 51 | \\"Batchfile\\", 52 | \\"Befunge\\", 53 | \\"Bison\\", 54 | \\"BitBake\\", 55 | \\"Blade\\", 56 | \\"BlitzBasic\\", 57 | \\"BlitzMax\\", 58 | \\"Bluespec\\", 59 | \\"Boo\\", 60 | \\"Brainfuck\\", 61 | \\"Brightscript\\", 62 | \\"Bro\\", 63 | \\"C\\", 64 | \\"C#\\", 65 | \\"C++\\", 66 | \\"C-ObjDump\\", 67 | \\"C2hs Haskell\\", 68 | \\"CLIPS\\", 69 | \\"CMake\\", 70 | \\"COBOL\\", 71 | \\"COLLADA\\", 72 | \\"CSON\\", 73 | \\"CSS\\", 74 | \\"CSV\\", 75 | \\"CWeb\\", 76 | \\"Cap'n Proto\\", 77 | \\"CartoCSS\\", 78 | \\"Ceylon\\", 79 | \\"Chapel\\", 80 | \\"Charity\\", 81 | \\"ChucK\\", 82 | \\"Cirru\\", 83 | \\"Clarion\\", 84 | \\"Clean\\", 85 | \\"Click\\", 86 | \\"Clojure\\", 87 | \\"Closure Templates\\", 88 | \\"CoNLL-U\\", 89 | \\"CoffeeScript\\", 90 | \\"ColdFusion\\", 91 | \\"ColdFusion CFC\\", 92 | \\"Common Lisp\\", 93 | \\"Common Workflow Language\\", 94 | \\"Component Pascal\\", 95 | \\"Cool\\", 96 | \\"Coq\\", 97 | \\"Cpp-ObjDump\\", 98 | \\"Creole\\", 99 | \\"Crystal\\", 100 | \\"Csound\\", 101 | \\"Csound Document\\", 102 | \\"Csound Score\\", 103 | \\"Cuda\\", 104 | \\"Cycript\\", 105 | \\"Cython\\", 106 | \\"D\\", 107 | \\"D-ObjDump\\", 108 | \\"DIGITAL Command Language\\", 109 | \\"DM\\", 110 | \\"DNS Zone\\", 111 | \\"DTrace\\", 112 | \\"Darcs Patch\\", 113 | \\"Dart\\", 114 | \\"DataWeave\\", 115 | \\"Diff\\", 116 | \\"Dockerfile\\", 117 | \\"Dogescript\\", 118 | \\"Dylan\\", 119 | \\"E\\", 120 | \\"EBNF\\", 121 | \\"ECL\\", 122 | \\"ECLiPSe\\", 123 | \\"EJS\\", 124 | \\"EQ\\", 125 | \\"Eagle\\", 126 | \\"Easybuild\\", 127 | \\"Ecere Projects\\", 128 | \\"Edje Data Collection\\", 129 | \\"Eiffel\\", 130 | \\"Elixir\\", 131 | \\"Elm\\", 132 | \\"Emacs Lisp\\", 133 | \\"EmberScript\\", 134 | \\"Erlang\\", 135 | \\"F#\\", 136 | \\"FLUX\\", 137 | \\"Factor\\", 138 | \\"Fancy\\", 139 | \\"Fantom\\", 140 | \\"Filebench WML\\", 141 | \\"Filterscript\\", 142 | \\"Formatted\\", 143 | \\"Forth\\", 144 | \\"Fortran\\", 145 | \\"FreeMarker\\", 146 | \\"Frege\\", 147 | \\"G-code\\", 148 | \\"GAMS\\", 149 | \\"GAP\\", 150 | \\"GCC Machine Description\\", 151 | \\"GDB\\", 152 | \\"GDScript\\", 153 | \\"GLSL\\", 154 | \\"GN\\", 155 | \\"Game Maker Language\\", 156 | \\"Genie\\", 157 | \\"Genshi\\", 158 | \\"Gentoo Ebuild\\", 159 | \\"Gentoo Eclass\\", 160 | \\"Gerber Image\\", 161 | \\"Gettext Catalog\\", 162 | \\"Gherkin\\", 163 | \\"Glyph\\", 164 | \\"Gnuplot\\", 165 | \\"Go\\", 166 | \\"Golo\\", 167 | \\"Gosu\\", 168 | \\"Grace\\", 169 | \\"Gradle\\", 170 | \\"Grammatical Framework\\", 171 | \\"Graph Modeling Language\\", 172 | \\"GraphQL\\", 173 | \\"Graphviz (DOT)\\", 174 | \\"Groovy\\", 175 | \\"Groovy Server Pages\\", 176 | \\"HCL\\", 177 | \\"HLSL\\", 178 | \\"HTML\\", 179 | \\"HTML+Django\\", 180 | \\"HTML+ECR\\", 181 | \\"HTML+EEX\\", 182 | \\"HTML+ERB\\", 183 | \\"HTML+PHP\\", 184 | \\"HTTP\\", 185 | \\"Hack\\", 186 | \\"Haml\\", 187 | \\"Handlebars\\", 188 | \\"Harbour\\", 189 | \\"Haskell\\", 190 | \\"Haxe\\", 191 | \\"Hy\\", 192 | \\"HyPhy\\", 193 | \\"IDL\\", 194 | \\"IGOR Pro\\", 195 | \\"INI\\", 196 | \\"IRC log\\", 197 | \\"Idris\\", 198 | \\"Inform 7\\", 199 | \\"Inno Setup\\", 200 | \\"Io\\", 201 | \\"Ioke\\", 202 | \\"Isabelle\\", 203 | \\"Isabelle ROOT\\", 204 | \\"J\\", 205 | \\"JFlex\\", 206 | \\"JSON\\", 207 | \\"JSON5\\", 208 | \\"JSONLD\\", 209 | \\"JSONiq\\", 210 | \\"JSX\\", 211 | \\"Jasmin\\", 212 | \\"Java\\", 213 | \\"Java Server Pages\\", 214 | \\"JavaScript\\", 215 | \\"Jison\\", 216 | \\"Jison Lex\\", 217 | \\"Jolie\\", 218 | \\"Julia\\", 219 | \\"Jupyter Notebook\\", 220 | \\"KRL\\", 221 | \\"KiCad Layout\\", 222 | \\"KiCad Legacy Layout\\", 223 | \\"KiCad Schematic\\", 224 | \\"Kit\\", 225 | \\"Kotlin\\", 226 | \\"LFE\\", 227 | \\"LLVM\\", 228 | \\"LOLCODE\\", 229 | \\"LSL\\", 230 | \\"LabVIEW\\", 231 | \\"Lasso\\", 232 | \\"Latte\\", 233 | \\"Lean\\", 234 | \\"Less\\", 235 | \\"Lex\\", 236 | \\"LilyPond\\", 237 | \\"Limbo\\", 238 | \\"Linker Script\\", 239 | \\"Linux Kernel Module\\", 240 | \\"Liquid\\", 241 | \\"Literate Agda\\", 242 | \\"Literate CoffeeScript\\", 243 | \\"Literate Haskell\\", 244 | \\"LiveScript\\", 245 | \\"Logos\\", 246 | \\"Logtalk\\", 247 | \\"LookML\\", 248 | \\"LoomScript\\", 249 | \\"Lua\\", 250 | \\"M\\", 251 | \\"M4\\", 252 | \\"M4Sugar\\", 253 | \\"MAXScript\\", 254 | \\"MQL4\\", 255 | \\"MQL5\\", 256 | \\"MTML\\", 257 | \\"MUF\\", 258 | \\"Makefile\\", 259 | \\"Mako\\", 260 | \\"Markdown\\", 261 | \\"Marko\\", 262 | \\"Mask\\", 263 | \\"Mathematica\\", 264 | \\"Matlab\\", 265 | \\"Maven POM\\", 266 | \\"Max\\", 267 | \\"MediaWiki\\", 268 | \\"Mercury\\", 269 | \\"Meson\\", 270 | \\"Metal\\", 271 | \\"MiniD\\", 272 | \\"Mirah\\", 273 | \\"Modelica\\", 274 | \\"Modula-2\\", 275 | \\"Module Management System\\", 276 | \\"Monkey\\", 277 | \\"Moocode\\", 278 | \\"MoonScript\\", 279 | \\"Mustache\\", 280 | \\"Myghty\\", 281 | \\"NCL\\", 282 | \\"NL\\", 283 | \\"NSIS\\", 284 | \\"Nearley\\", 285 | \\"Nemerle\\", 286 | \\"NetLinx\\", 287 | \\"NetLinx+ERB\\", 288 | \\"NetLogo\\", 289 | \\"NewLisp\\", 290 | \\"Nextflow\\", 291 | \\"Nginx\\", 292 | \\"Nim\\", 293 | \\"Ninja\\", 294 | \\"Nit\\", 295 | \\"Nix\\", 296 | \\"Nu\\", 297 | \\"NumPy\\", 298 | \\"OCaml\\", 299 | \\"ObjDump\\", 300 | \\"Objective-C\\", 301 | \\"Objective-C++\\", 302 | \\"Objective-J\\", 303 | \\"Omgrofl\\", 304 | \\"Opa\\", 305 | \\"Opal\\", 306 | \\"OpenCL\\", 307 | \\"OpenEdge ABL\\", 308 | \\"OpenRC runscript\\", 309 | \\"OpenSCAD\\", 310 | \\"OpenType Feature File\\", 311 | \\"Org\\", 312 | \\"Ox\\", 313 | \\"Oxygene\\", 314 | \\"Oz\\", 315 | \\"P4\\", 316 | \\"PAWN\\", 317 | \\"PHP\\", 318 | \\"PLSQL\\", 319 | \\"PLpgSQL\\", 320 | \\"POV-Ray SDL\\", 321 | \\"Pan\\", 322 | \\"Papyrus\\", 323 | \\"Parrot\\", 324 | \\"Parrot Assembly\\", 325 | \\"Parrot Internal Representation\\", 326 | \\"Pascal\\", 327 | \\"Pep8\\", 328 | \\"Perl\\", 329 | \\"Perl 6\\", 330 | \\"Pic\\", 331 | \\"Pickle\\", 332 | \\"PicoLisp\\", 333 | \\"PigLatin\\", 334 | \\"Pike\\", 335 | \\"Pod\\", 336 | \\"PogoScript\\", 337 | \\"Pony\\", 338 | \\"PostCSS\\", 339 | \\"PostScript\\", 340 | \\"PowerBuilder\\", 341 | \\"PowerShell\\", 342 | \\"Processing\\", 343 | \\"Prolog\\", 344 | \\"Propeller Spin\\", 345 | \\"Protocol Buffer\\", 346 | \\"Public Key\\", 347 | \\"Pug\\", 348 | \\"Puppet\\", 349 | \\"Pure Data\\", 350 | \\"PureBasic\\", 351 | \\"PureScript\\", 352 | \\"Python\\", 353 | \\"Python console\\", 354 | \\"Python traceback\\", 355 | \\"QML\\", 356 | \\"QMake\\", 357 | \\"R\\", 358 | \\"RAML\\", 359 | \\"RDoc\\", 360 | \\"REALbasic\\", 361 | \\"REXX\\", 362 | \\"RHTML\\", 363 | \\"RMarkdown\\", 364 | \\"RPC\\", 365 | \\"RPM Spec\\", 366 | \\"RUNOFF\\", 367 | \\"Racket\\", 368 | \\"Ragel\\", 369 | \\"Rascal\\", 370 | \\"Raw token data\\", 371 | \\"Reason\\", 372 | \\"Rebol\\", 373 | \\"Red\\", 374 | \\"Redcode\\", 375 | \\"Regular Expression\\", 376 | \\"Ren'Py\\", 377 | \\"RenderScript\\", 378 | \\"Ring\\", 379 | \\"Riot\\", 380 | \\"RobotFramework\\", 381 | \\"Roff\\", 382 | \\"Rouge\\", 383 | \\"Ruby\\", 384 | \\"Rust\\", 385 | \\"SAS\\", 386 | \\"SCSS\\", 387 | \\"SMT\\", 388 | \\"SPARQL\\", 389 | \\"SQF\\", 390 | \\"SQL\\", 391 | \\"SQLPL\\", 392 | \\"SRecode Template\\", 393 | \\"STON\\", 394 | \\"SVG\\", 395 | \\"Sage\\", 396 | \\"SaltStack\\", 397 | \\"Sass\\", 398 | \\"Scala\\", 399 | \\"Scaml\\", 400 | \\"Scheme\\", 401 | \\"Scilab\\", 402 | \\"Self\\", 403 | \\"ShaderLab\\", 404 | \\"Shell\\", 405 | \\"ShellSession\\", 406 | \\"Shen\\", 407 | \\"Slash\\", 408 | \\"Slim\\", 409 | \\"Smali\\", 410 | \\"Smalltalk\\", 411 | \\"Smarty\\", 412 | \\"Solidity\\", 413 | \\"SourcePawn\\", 414 | \\"Spacebars\\", 415 | \\"Spline Font Database\\", 416 | \\"Squirrel\\", 417 | \\"Stan\\", 418 | \\"Standard ML\\", 419 | \\"Stata\\", 420 | \\"Stylus\\", 421 | \\"SubRip Text\\", 422 | \\"Sublime Text Config\\", 423 | \\"SugarSS\\", 424 | \\"SuperCollider\\", 425 | \\"Swift\\", 426 | \\"Swig\\", 427 | \\"SystemVerilog\\", 428 | \\"TI Program\\", 429 | \\"TLA\\", 430 | \\"TOML\\", 431 | \\"TXL\\", 432 | \\"Tcl\\", 433 | \\"Tcsh\\", 434 | \\"TeX\\", 435 | \\"Tea\\", 436 | \\"Terra\\", 437 | \\"Text\\", 438 | \\"Textile\\", 439 | \\"Thrift\\", 440 | \\"Titanium Style Sheets\\", 441 | \\"Turing\\", 442 | \\"Turtle\\", 443 | \\"Twig\\", 444 | \\"Type Language\\", 445 | \\"TypeScript\\", 446 | \\"Unified Parallel C\\", 447 | \\"Unity3D Asset\\", 448 | \\"Unix Assembly\\", 449 | \\"Uno\\", 450 | \\"UnrealScript\\", 451 | \\"UrWeb\\", 452 | \\"VCL\\", 453 | \\"VHDL\\", 454 | \\"Vala\\", 455 | \\"Verilog\\", 456 | \\"Vim script\\", 457 | \\"Visual Basic\\", 458 | \\"Visualforce\\", 459 | \\"Volt\\", 460 | \\"Vue\\", 461 | \\"Wavefront Material\\", 462 | \\"Wavefront Object\\", 463 | \\"Web Ontology Language\\", 464 | \\"WebAssembly\\", 465 | \\"WebIDL\\", 466 | \\"World of Warcraft Addon Data\\", 467 | \\"X10\\", 468 | \\"XC\\", 469 | \\"XCompose\\", 470 | \\"XML\\", 471 | \\"XPM\\", 472 | \\"XPages\\", 473 | \\"XProc\\", 474 | \\"XQuery\\", 475 | \\"XS\\", 476 | \\"XSLT\\", 477 | \\"XTemplate\\", 478 | \\"Xojo\\", 479 | \\"Xtend\\", 480 | \\"YAML\\", 481 | \\"YANG\\", 482 | \\"YARA\\", 483 | \\"Yacc\\", 484 | \\"Zephir\\", 485 | \\"Zimpl\\", 486 | \\"desktop\\", 487 | \\"eC\\", 488 | \\"edn\\", 489 | \\"fish\\", 490 | \\"mupad\\", 491 | \\"nesC\\", 492 | \\"ooc\\", 493 | \\"reStructuredText\\", 494 | \\"wdl\\", 495 | \\"wisp\\", 496 | \\"xBase\\" 497 | ] 498 | } 499 | ", 500 | } 501 | `; 502 | 503 | exports[`SupportCommand Support without JSON installed beautifiers 1`] = ` 504 | Object { 505 | "exitCode": 0, 506 | "stderr": "", 507 | "stdout": "Supported beautifiers 508 | 1. @unibeautify/beautifier-eslint 509 | ", 510 | } 511 | `; 512 | 513 | exports[`SupportCommand Support without JSON languages 1`] = ` 514 | Object { 515 | "exitCode": 0, 516 | "stderr": "", 517 | "stdout": "Supported languages 518 | 1. 1C Enterprise 519 | 2. ABAP 520 | 3. ABNF 521 | 4. AGS Script 522 | 5. AMPL 523 | 6. ANTLR 524 | 7. API Blueprint 525 | 8. APL 526 | 9. ASN.1 527 | 10. ASP 528 | 11. ATS 529 | 12. ActionScript 530 | 13. Ada 531 | 14. Adobe Font Metrics 532 | 15. Agda 533 | 16. Alloy 534 | 17. Alpine Abuild 535 | 18. AngelScript 536 | 19. Ant Build System 537 | 20. ApacheConf 538 | 21. Apex 539 | 22. Apollo Guidance Computer 540 | 23. AppleScript 541 | 24. Arc 542 | 25. Arduino 543 | 26. AsciiDoc 544 | 27. AspectJ 545 | 28. Assembly 546 | 29. Augeas 547 | 30. AutoHotkey 548 | 31. AutoIt 549 | 32. Awk 550 | 33. Ballerina 551 | 34. Batchfile 552 | 35. Befunge 553 | 36. Bison 554 | 37. BitBake 555 | 38. Blade 556 | 39. BlitzBasic 557 | 40. BlitzMax 558 | 41. Bluespec 559 | 42. Boo 560 | 43. Brainfuck 561 | 44. Brightscript 562 | 45. Bro 563 | 46. C 564 | 47. C# 565 | 48. C++ 566 | 49. C-ObjDump 567 | 50. C2hs Haskell 568 | 51. CLIPS 569 | 52. CMake 570 | 53. COBOL 571 | 54. COLLADA 572 | 55. CSON 573 | 56. CSS 574 | 57. CSV 575 | 58. CWeb 576 | 59. Cap'n Proto 577 | 60. CartoCSS 578 | 61. Ceylon 579 | 62. Chapel 580 | 63. Charity 581 | 64. ChucK 582 | 65. Cirru 583 | 66. Clarion 584 | 67. Clean 585 | 68. Click 586 | 69. Clojure 587 | 70. Closure Templates 588 | 71. CoNLL-U 589 | 72. CoffeeScript 590 | 73. ColdFusion 591 | 74. ColdFusion CFC 592 | 75. Common Lisp 593 | 76. Common Workflow Language 594 | 77. Component Pascal 595 | 78. Cool 596 | 79. Coq 597 | 80. Cpp-ObjDump 598 | 81. Creole 599 | 82. Crystal 600 | 83. Csound 601 | 84. Csound Document 602 | 85. Csound Score 603 | 86. Cuda 604 | 87. Cycript 605 | 88. Cython 606 | 89. D 607 | 90. D-ObjDump 608 | 91. DIGITAL Command Language 609 | 92. DM 610 | 93. DNS Zone 611 | 94. DTrace 612 | 95. Darcs Patch 613 | 96. Dart 614 | 97. DataWeave 615 | 98. Diff 616 | 99. Dockerfile 617 | 100. Dogescript 618 | 101. Dylan 619 | 102. E 620 | 103. EBNF 621 | 104. ECL 622 | 105. ECLiPSe 623 | 106. EJS 624 | 107. EQ 625 | 108. Eagle 626 | 109. Easybuild 627 | 110. Ecere Projects 628 | 111. Edje Data Collection 629 | 112. Eiffel 630 | 113. Elixir 631 | 114. Elm 632 | 115. Emacs Lisp 633 | 116. EmberScript 634 | 117. Erlang 635 | 118. F# 636 | 119. FLUX 637 | 120. Factor 638 | 121. Fancy 639 | 122. Fantom 640 | 123. Filebench WML 641 | 124. Filterscript 642 | 125. Formatted 643 | 126. Forth 644 | 127. Fortran 645 | 128. FreeMarker 646 | 129. Frege 647 | 130. G-code 648 | 131. GAMS 649 | 132. GAP 650 | 133. GCC Machine Description 651 | 134. GDB 652 | 135. GDScript 653 | 136. GLSL 654 | 137. GN 655 | 138. Game Maker Language 656 | 139. Genie 657 | 140. Genshi 658 | 141. Gentoo Ebuild 659 | 142. Gentoo Eclass 660 | 143. Gerber Image 661 | 144. Gettext Catalog 662 | 145. Gherkin 663 | 146. Glyph 664 | 147. Gnuplot 665 | 148. Go 666 | 149. Golo 667 | 150. Gosu 668 | 151. Grace 669 | 152. Gradle 670 | 153. Grammatical Framework 671 | 154. Graph Modeling Language 672 | 155. GraphQL 673 | 156. Graphviz (DOT) 674 | 157. Groovy 675 | 158. Groovy Server Pages 676 | 159. HCL 677 | 160. HLSL 678 | 161. HTML 679 | 162. HTML+Django 680 | 163. HTML+ECR 681 | 164. HTML+EEX 682 | 165. HTML+ERB 683 | 166. HTML+PHP 684 | 167. HTTP 685 | 168. Hack 686 | 169. Haml 687 | 170. Handlebars 688 | 171. Harbour 689 | 172. Haskell 690 | 173. Haxe 691 | 174. Hy 692 | 175. HyPhy 693 | 176. IDL 694 | 177. IGOR Pro 695 | 178. INI 696 | 179. IRC log 697 | 180. Idris 698 | 181. Inform 7 699 | 182. Inno Setup 700 | 183. Io 701 | 184. Ioke 702 | 185. Isabelle 703 | 186. Isabelle ROOT 704 | 187. J 705 | 188. JFlex 706 | 189. JSON 707 | 190. JSON5 708 | 191. JSONLD 709 | 192. JSONiq 710 | 193. JSX 711 | 194. Jasmin 712 | 195. Java 713 | 196. Java Server Pages 714 | 197. JavaScript 715 | 198. Jison 716 | 199. Jison Lex 717 | 200. Jolie 718 | 201. Julia 719 | 202. Jupyter Notebook 720 | 203. KRL 721 | 204. KiCad Layout 722 | 205. KiCad Legacy Layout 723 | 206. KiCad Schematic 724 | 207. Kit 725 | 208. Kotlin 726 | 209. LFE 727 | 210. LLVM 728 | 211. LOLCODE 729 | 212. LSL 730 | 213. LabVIEW 731 | 214. Lasso 732 | 215. Latte 733 | 216. Lean 734 | 217. Less 735 | 218. Lex 736 | 219. LilyPond 737 | 220. Limbo 738 | 221. Linker Script 739 | 222. Linux Kernel Module 740 | 223. Liquid 741 | 224. Literate Agda 742 | 225. Literate CoffeeScript 743 | 226. Literate Haskell 744 | 227. LiveScript 745 | 228. Logos 746 | 229. Logtalk 747 | 230. LookML 748 | 231. LoomScript 749 | 232. Lua 750 | 233. M 751 | 234. M4 752 | 235. M4Sugar 753 | 236. MAXScript 754 | 237. MQL4 755 | 238. MQL5 756 | 239. MTML 757 | 240. MUF 758 | 241. Makefile 759 | 242. Mako 760 | 243. Markdown 761 | 244. Marko 762 | 245. Mask 763 | 246. Mathematica 764 | 247. Matlab 765 | 248. Maven POM 766 | 249. Max 767 | 250. MediaWiki 768 | 251. Mercury 769 | 252. Meson 770 | 253. Metal 771 | 254. MiniD 772 | 255. Mirah 773 | 256. Modelica 774 | 257. Modula-2 775 | 258. Module Management System 776 | 259. Monkey 777 | 260. Moocode 778 | 261. MoonScript 779 | 262. Mustache 780 | 263. Myghty 781 | 264. NCL 782 | 265. NL 783 | 266. NSIS 784 | 267. Nearley 785 | 268. Nemerle 786 | 269. NetLinx 787 | 270. NetLinx+ERB 788 | 271. NetLogo 789 | 272. NewLisp 790 | 273. Nextflow 791 | 274. Nginx 792 | 275. Nim 793 | 276. Ninja 794 | 277. Nit 795 | 278. Nix 796 | 279. Nu 797 | 280. NumPy 798 | 281. OCaml 799 | 282. ObjDump 800 | 283. Objective-C 801 | 284. Objective-C++ 802 | 285. Objective-J 803 | 286. Omgrofl 804 | 287. Opa 805 | 288. Opal 806 | 289. OpenCL 807 | 290. OpenEdge ABL 808 | 291. OpenRC runscript 809 | 292. OpenSCAD 810 | 293. OpenType Feature File 811 | 294. Org 812 | 295. Ox 813 | 296. Oxygene 814 | 297. Oz 815 | 298. P4 816 | 299. PAWN 817 | 300. PHP 818 | 301. PLSQL 819 | 302. PLpgSQL 820 | 303. POV-Ray SDL 821 | 304. Pan 822 | 305. Papyrus 823 | 306. Parrot 824 | 307. Parrot Assembly 825 | 308. Parrot Internal Representation 826 | 309. Pascal 827 | 310. Pep8 828 | 311. Perl 829 | 312. Perl 6 830 | 313. Pic 831 | 314. Pickle 832 | 315. PicoLisp 833 | 316. PigLatin 834 | 317. Pike 835 | 318. Pod 836 | 319. PogoScript 837 | 320. Pony 838 | 321. PostCSS 839 | 322. PostScript 840 | 323. PowerBuilder 841 | 324. PowerShell 842 | 325. Processing 843 | 326. Prolog 844 | 327. Propeller Spin 845 | 328. Protocol Buffer 846 | 329. Public Key 847 | 330. Pug 848 | 331. Puppet 849 | 332. Pure Data 850 | 333. PureBasic 851 | 334. PureScript 852 | 335. Python 853 | 336. Python console 854 | 337. Python traceback 855 | 338. QML 856 | 339. QMake 857 | 340. R 858 | 341. RAML 859 | 342. RDoc 860 | 343. REALbasic 861 | 344. REXX 862 | 345. RHTML 863 | 346. RMarkdown 864 | 347. RPC 865 | 348. RPM Spec 866 | 349. RUNOFF 867 | 350. Racket 868 | 351. Ragel 869 | 352. Rascal 870 | 353. Raw token data 871 | 354. Reason 872 | 355. Rebol 873 | 356. Red 874 | 357. Redcode 875 | 358. Regular Expression 876 | 359. Ren'Py 877 | 360. RenderScript 878 | 361. Ring 879 | 362. Riot 880 | 363. RobotFramework 881 | 364. Roff 882 | 365. Rouge 883 | 366. Ruby 884 | 367. Rust 885 | 368. SAS 886 | 369. SCSS 887 | 370. SMT 888 | 371. SPARQL 889 | 372. SQF 890 | 373. SQL 891 | 374. SQLPL 892 | 375. SRecode Template 893 | 376. STON 894 | 377. SVG 895 | 378. Sage 896 | 379. SaltStack 897 | 380. Sass 898 | 381. Scala 899 | 382. Scaml 900 | 383. Scheme 901 | 384. Scilab 902 | 385. Self 903 | 386. ShaderLab 904 | 387. Shell 905 | 388. ShellSession 906 | 389. Shen 907 | 390. Slash 908 | 391. Slim 909 | 392. Smali 910 | 393. Smalltalk 911 | 394. Smarty 912 | 395. Solidity 913 | 396. SourcePawn 914 | 397. Spacebars 915 | 398. Spline Font Database 916 | 399. Squirrel 917 | 400. Stan 918 | 401. Standard ML 919 | 402. Stata 920 | 403. Stylus 921 | 404. SubRip Text 922 | 405. Sublime Text Config 923 | 406. SugarSS 924 | 407. SuperCollider 925 | 408. Swift 926 | 409. Swig 927 | 410. SystemVerilog 928 | 411. TI Program 929 | 412. TLA 930 | 413. TOML 931 | 414. TXL 932 | 415. Tcl 933 | 416. Tcsh 934 | 417. TeX 935 | 418. Tea 936 | 419. Terra 937 | 420. Text 938 | 421. Textile 939 | 422. Thrift 940 | 423. Titanium Style Sheets 941 | 424. Turing 942 | 425. Turtle 943 | 426. Twig 944 | 427. Type Language 945 | 428. TypeScript 946 | 429. Unified Parallel C 947 | 430. Unity3D Asset 948 | 431. Unix Assembly 949 | 432. Uno 950 | 433. UnrealScript 951 | 434. UrWeb 952 | 435. VCL 953 | 436. VHDL 954 | 437. Vala 955 | 438. Verilog 956 | 439. Vim script 957 | 440. Visual Basic 958 | 441. Visualforce 959 | 442. Volt 960 | 443. Vue 961 | 444. Wavefront Material 962 | 445. Wavefront Object 963 | 446. Web Ontology Language 964 | 447. WebAssembly 965 | 448. WebIDL 966 | 449. World of Warcraft Addon Data 967 | 450. X10 968 | 451. XC 969 | 452. XCompose 970 | 453. XML 971 | 454. XPM 972 | 455. XPages 973 | 456. XProc 974 | 457. XQuery 975 | 458. XS 976 | 459. XSLT 977 | 460. XTemplate 978 | 461. Xojo 979 | 462. Xtend 980 | 463. YAML 981 | 464. YANG 982 | 465. YARA 983 | 466. Yacc 984 | 467. Zephir 985 | 468. Zimpl 986 | 469. desktop 987 | 470. eC 988 | 471. edn 989 | 472. fish 990 | 473. mupad 991 | 474. nesC 992 | 475. ooc 993 | 476. reStructuredText 994 | 477. wdl 995 | 478. wisp 996 | 479. xBase 997 | ", 998 | } 999 | `; 1000 | 1001 | exports[`SupportCommand Support without JSON supported languages 1`] = ` 1002 | Object { 1003 | "exitCode": 0, 1004 | "stderr": "", 1005 | "stdout": "Supported languages 1006 | 1. JSX 1007 | 2. JavaScript 1008 | ", 1009 | } 1010 | `; 1011 | --------------------------------------------------------------------------------