From 03eae9e085f6020a017ecbe761cccac9a5a89d77 Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Fri, 20 Sep 2019 22:04:44 +0900 Subject: [PATCH 1/4] Fix 2777 - Add IBM openapi validator --- ale_linters/openapi/ibm_validator.vim | 58 +++++++++++++++++++ doc/ale-openapi.txt | 42 ++++++++++++++ doc/ale-supported-languages-and-tools.txt | 2 + doc/ale.txt | 2 + supported-tools.md | 2 + ...m_openapi_validator_command_callback.vader | 15 +++++ .../test_ibm_openapi_validator_handler.vader | 49 ++++++++++++++++ 7 files changed, 170 insertions(+) create mode 100644 ale_linters/openapi/ibm_validator.vim create mode 100644 doc/ale-openapi.txt create mode 100644 test/command_callback/test_ibm_openapi_validator_command_callback.vader create mode 100644 test/handler/test_ibm_openapi_validator_handler.vader diff --git a/ale_linters/openapi/ibm_validator.vim b/ale_linters/openapi/ibm_validator.vim new file mode 100644 index 00000000..c54741d2 --- /dev/null +++ b/ale_linters/openapi/ibm_validator.vim @@ -0,0 +1,58 @@ +" Author: Horacio Sanson + +call ale#Set('openapi_ibm_validator_executable', 'lint-openapi') +call ale#Set('openapi_ibm_validator_options', '') + +function! ale_linters#openapi#ibm_validator#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'openapi_ibm_validator_options')) + \ . ' %t' +endfunction + +function! ale_linters#openapi#ibm_validator#Handle(buffer, lines) abort + let l:output = [] + let l:type = 'E' + let l:message = '' + let l:nr = -1 + + for l:line in a:lines + let l:match = matchlist(l:line, '^errors$') + + if !empty(l:match) + let l:type = 'E' + endif + + let l:match = matchlist(l:line, '^warnings$') + + if !empty(l:match) + let l:type = 'W' + endif + + let l:match = matchlist(l:line, '^ *Message : *\(.\+\)$') + + if !empty(l:match) + let l:message = l:match[1] + endif + + let l:match = matchlist(l:line, '^ *Line *: *\(\d\+\)$') + + if !empty(l:match) + let l:nr = l:match[1] + + call add(l:output, { + \ 'lnum': l:nr + 0, + \ 'col': 0, + \ 'text': l:message, + \ 'type': l:type, + \}) + endif + endfor + + return l:output +endfunction + +call ale#linter#Define('openapi', { +\ 'name': 'ibm-validator', +\ 'executable': {b -> ale#Var(b, 'openapi_ibm_validator_executable')}, +\ 'command': function('ale_linters#openapi#ibm_validator#GetCommand'), +\ 'callback': 'ale_linters#openapi#ibm_validator#Handle', +\}) diff --git a/doc/ale-openapi.txt b/doc/ale-openapi.txt new file mode 100644 index 00000000..d0ab9bfc --- /dev/null +++ b/doc/ale-openapi.txt @@ -0,0 +1,42 @@ +=============================================================================== +ALE OpenApi Integration *ale-openapi-options* + +=============================================================================== +ibm-validator *ale-openapi-ibm-validator* + +Website: https://github.com/IBM/openapi-validator + + +Installation +------------------------------------------------------------------------------- + +Install ibm-openapi-validator either globally or locally: > + + npm install ibm-openapi-validator -g # global + npm install ibm-openapi-validator # local +< +Recommended plugin for openapi filetype detection: + + https://github.com/hsanson/vim-openapi + +Options +------------------------------------------------------------------------------- + +g:ale_openapi_ibm_validator_executable *g:ale_openapi_ibm_validator_executable* + *b:ale_openapi_ibm_validator_executable* + Type: |String| + Default: `'lint-openapi'` + + This variable can be set to change the path to lint-openapi. + + +g:ale_openapi_ibm_validator_options *g:ale_openapi_ibm_validator_options* + *b:ale_openapi_ibm_validator_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to lint-openapi. + + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 5476be47..b73bec4f 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -322,6 +322,8 @@ Notes: * `ocamlformat` * `ocp-indent` * `ols` +* OpenApi + * `ibm-validator` * Pawn * `uncrustify` * Perl diff --git a/doc/ale.txt b/doc/ale.txt index 721ca69d..68ac8498 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2835,6 +2835,8 @@ documented in additional help files. ols...................................|ale-ocaml-ols| ocamlformat...........................|ale-ocaml-ocamlformat| ocp-indent............................|ale-ocaml-ocp-indent| + openapi.................................|ale-openapi-options| + ibm-validator.........................|ale-openapi-ibm-validator| pawn....................................|ale-pawn-options| uncrustify............................|ale-pawn-uncrustify| perl....................................|ale-perl-options| diff --git a/supported-tools.md b/supported-tools.md index b07f6acf..a74fdd99 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -331,6 +331,8 @@ formatting. * [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) * [ocp-indent](https://github.com/OCamlPro/ocp-indent) * [ols](https://github.com/freebroccolo/ocaml-language-server) +* OpenApi + * [ibm-validator](https://github.com/IBM/openapi-validator) * Pawn * [uncrustify](https://github.com/uncrustify/uncrustify) * Perl diff --git a/test/command_callback/test_ibm_openapi_validator_command_callback.vader b/test/command_callback/test_ibm_openapi_validator_command_callback.vader new file mode 100644 index 00000000..3484cc09 --- /dev/null +++ b/test/command_callback/test_ibm_openapi_validator_command_callback.vader @@ -0,0 +1,15 @@ +Before: + call ale#assert#SetUpLinterTest('openapi', 'ibm_validator') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The yaml ibm-openapi-validator command callback should return the correct default string): + AssertLinter 'lint-openapi', ale#Escape('lint-openapi') . ' %t' + +Execute(The yaml ibm-openapi-validator command callback should be configurable): + let g:ale_openapi_ibm_validator_executable = '~/.local/bin/lint-openapi' + let g:ale_openapi_ibm_validator_options = '-c ~/.config' + + AssertLinter '~/.local/bin/lint-openapi', ale#Escape('~/.local/bin/lint-openapi') + \ . ' -c ~/.config %t' diff --git a/test/handler/test_ibm_openapi_validator_handler.vader b/test/handler/test_ibm_openapi_validator_handler.vader new file mode 100644 index 00000000..e136d5d2 --- /dev/null +++ b/test/handler/test_ibm_openapi_validator_handler.vader @@ -0,0 +1,49 @@ +Before: + runtime! ale_linters/openapi/ibm_validator.vim + +After: + call ale#linter#Reset() + +Execute(Problems should be parsed correctly for openapi-ibm-validator): + AssertEqual + \ [ + \ { + \ 'lnum': 54, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'Items with a description must have content in it.', + \ }, + \ { + \ 'lnum': 24, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'Operations must have a non-empty `operationId`.', + \ }, + \ { + \ 'lnum': 40, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'operationIds must follow case convention: lower_snake_case', + \ }, + \ ], + \ ale_linters#openapi#ibm_validator#Handle(bufnr(''), [ + \ '', + \ '[Warning] No .validaterc file found. The validator will run in default mode.', + \ 'To configure the validator, create a .validaterc file.', + \ '', + \ 'errors', + \ '', + \ ' Message : Items with a description must have content in it.', + \ ' Path : paths./settings.patch.description', + \ ' Line : 54', + \ '', + \ 'warnings', + \ '', + \ ' Message : Operations must have a non-empty `operationId`.', + \ ' Path : paths./stats.get.operationId', + \ ' Line : 24', + \ '', + \ ' Message : operationIds must follow case convention: lower_snake_case', + \ ' Path : paths./settings.get.operationId', + \ ' Line : 40' + \ ]) From 014b00d4d778bbfe027e927183b44ce3424679b4 Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Sun, 27 Oct 2019 00:16:23 +0900 Subject: [PATCH 2/4] Add yamllint and prettier to openapi. This commit enables yamllint and prettier on openapi files. --- ale_linters/openapi/yamllint.vim | 9 +++++ ale_linters/yaml/yamllint.vim | 43 ++--------------------- autoload/ale/fix/registry.vim | 2 +- autoload/ale/fixers/prettier.vim | 1 + autoload/ale/handlers/yamllint.vim | 39 ++++++++++++++++++++ doc/ale-openapi.txt | 12 +++++++ doc/ale-supported-languages-and-tools.txt | 2 ++ doc/ale.txt | 2 ++ supported-tools.md | 2 ++ test/handler/test_yamllint_handler.vader | 8 ++--- 10 files changed, 74 insertions(+), 46 deletions(-) create mode 100644 ale_linters/openapi/yamllint.vim create mode 100644 autoload/ale/handlers/yamllint.vim diff --git a/ale_linters/openapi/yamllint.vim b/ale_linters/openapi/yamllint.vim new file mode 100644 index 00000000..2b8952cc --- /dev/null +++ b/ale_linters/openapi/yamllint.vim @@ -0,0 +1,9 @@ +call ale#Set('yaml_yamllint_executable', 'yamllint') +call ale#Set('yaml_yamllint_options', '') + +call ale#linter#Define('openapi', { +\ 'name': 'yamllint', +\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')}, +\ 'command': function('ale#handlers#yamllint#GetCommand'), +\ 'callback': 'ale#handlers#yamllint#Handle', +\}) diff --git a/ale_linters/yaml/yamllint.vim b/ale_linters/yaml/yamllint.vim index bedb7bf1..39011df1 100644 --- a/ale_linters/yaml/yamllint.vim +++ b/ale_linters/yaml/yamllint.vim @@ -3,48 +3,9 @@ call ale#Set('yaml_yamllint_executable', 'yamllint') call ale#Set('yaml_yamllint_options', '') -function! ale_linters#yaml#yamllint#GetCommand(buffer) abort - return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options')) - \ . ' -f parsable %t' -endfunction - -function! ale_linters#yaml#yamllint#Handle(buffer, lines) abort - " Matches patterns line the following: - " something.yaml:1:1: [warning] missing document start "---" (document-start) - " something.yml:2:1: [error] syntax error: expected the node content, but found '' - let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$' - let l:output = [] - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - let l:item = { - \ 'lnum': l:match[1] + 0, - \ 'col': l:match[2] + 0, - \ 'text': l:match[4], - \ 'type': l:match[3] is# 'error' ? 'E' : 'W', - \} - - let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$') - - if !empty(l:code_match) - if l:code_match[2] is# 'trailing-spaces' - \&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace') - " Skip warnings for trailing whitespace if the option is off. - continue - endif - - let l:item.text = l:code_match[1] - let l:item.code = l:code_match[2] - endif - - call add(l:output, l:item) - endfor - - return l:output -endfunction - call ale#linter#Define('yaml', { \ 'name': 'yamllint', \ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')}, -\ 'command': function('ale_linters#yaml#yamllint#GetCommand'), -\ 'callback': 'ale_linters#yaml#yamllint#Handle', +\ 'command': function('ale#handlers#yamllint#GetCommand'), +\ 'callback': 'ale#handlers#yamllint#Handle', \}) diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index f514466e..4564954b 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -102,7 +102,7 @@ let s:default_registry = { \ }, \ 'prettier': { \ 'function': 'ale#fixers#prettier#Fix', -\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue', 'html', 'yaml'], +\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue', 'html', 'yaml', 'openapi'], \ 'description': 'Apply prettier to a file.', \ }, \ 'prettier_eslint': { diff --git a/autoload/ale/fixers/prettier.vim b/autoload/ale/fixers/prettier.vim index e0f4972e..12c018af 100644 --- a/autoload/ale/fixers/prettier.vim +++ b/autoload/ale/fixers/prettier.vim @@ -83,6 +83,7 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version) abort \ 'markdown': 'markdown', \ 'vue': 'vue', \ 'yaml': 'yaml', + \ 'openapi': 'yaml', \ 'html': 'html', \} diff --git a/autoload/ale/handlers/yamllint.vim b/autoload/ale/handlers/yamllint.vim new file mode 100644 index 00000000..5e04577d --- /dev/null +++ b/autoload/ale/handlers/yamllint.vim @@ -0,0 +1,39 @@ +function! ale#handlers#yamllint#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options')) + \ . ' -f parsable %t' +endfunction + +function! ale#handlers#yamllint#Handle(buffer, lines) abort + " Matches patterns line the following: + " something.yaml:1:1: [warning] missing document start "---" (document-start) + " something.yml:2:1: [error] syntax error: expected the node content, but found '' + let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + let l:item = { + \ 'lnum': l:match[1] + 0, + \ 'col': l:match[2] + 0, + \ 'text': l:match[4], + \ 'type': l:match[3] is# 'error' ? 'E' : 'W', + \} + + let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$') + + if !empty(l:code_match) + if l:code_match[2] is# 'trailing-spaces' + \&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace') + " Skip warnings for trailing whitespace if the option is off. + continue + endif + + let l:item.text = l:code_match[1] + let l:item.code = l:code_match[2] + endif + + call add(l:output, l:item) + endfor + + return l:output +endfunction + diff --git a/doc/ale-openapi.txt b/doc/ale-openapi.txt index d0ab9bfc..27261de6 100644 --- a/doc/ale-openapi.txt +++ b/doc/ale-openapi.txt @@ -38,5 +38,17 @@ g:ale_openapi_ibm_validator_options *g:ale_openapi_ibm_validator_options* This variable can be set to pass additional options to lint-openapi. +=============================================================================== +prettier *ale-openapi-prettier* + +See |ale-javascript-prettier| for information about the available options. + + +=============================================================================== +yamllint *ale-openapi-yamllint* + +See |ale-yaml-yamllint| for information about the available options. + + =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index b73bec4f..57eb71dc 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -324,6 +324,8 @@ Notes: * `ols` * OpenApi * `ibm-validator` + * `prettier` + * `yamllint` * Pawn * `uncrustify` * Perl diff --git a/doc/ale.txt b/doc/ale.txt index 68ac8498..b2cea4cd 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2837,6 +2837,8 @@ documented in additional help files. ocp-indent............................|ale-ocaml-ocp-indent| openapi.................................|ale-openapi-options| ibm-validator.........................|ale-openapi-ibm-validator| + prettier..............................|ale-openapi-prettier| + yamllint..............................|ale-openapi-yamllint| pawn....................................|ale-pawn-options| uncrustify............................|ale-pawn-uncrustify| perl....................................|ale-perl-options| diff --git a/supported-tools.md b/supported-tools.md index a74fdd99..df9071f8 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -333,6 +333,8 @@ formatting. * [ols](https://github.com/freebroccolo/ocaml-language-server) * OpenApi * [ibm-validator](https://github.com/IBM/openapi-validator) + * [prettier](https://github.com/prettier/prettier) + * [yamllint](https://yamllint.readthedocs.io/) * Pawn * [uncrustify](https://github.com/uncrustify/uncrustify) * Perl diff --git a/test/handler/test_yamllint_handler.vader b/test/handler/test_yamllint_handler.vader index 1aa0b9f5..dd51119c 100644 --- a/test/handler/test_yamllint_handler.vader +++ b/test/handler/test_yamllint_handler.vader @@ -3,7 +3,7 @@ Before: let g:ale_warn_about_trailing_whitespace = 1 - runtime! ale_linters/yaml/yamllint.vim + runtime! ale/handlers/yamllint.vim After: Restore @@ -29,7 +29,7 @@ Execute(Problems should be parsed correctly for yamllint): \ 'text': 'syntax error: expected the node content, but found ''''', \ }, \ ], - \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ ale#handlers#yamllint#Handle(bufnr(''), [ \ 'something.yaml:1:1: [warning] missing document start "---" (document-start)', \ 'something.yml:2:1: [error] syntax error: expected the node content, but found ''''', \ ]) @@ -45,7 +45,7 @@ Execute(The yamllint handler should respect ale_warn_about_trailing_whitespace): \ 'code': 'trailing-spaces', \ }, \ ], - \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ ale#handlers#yamllint#Handle(bufnr(''), [ \ 'something.yml:5:18: [error] trailing spaces (trailing-spaces)', \ ]) @@ -54,6 +54,6 @@ Execute(The yamllint handler should respect ale_warn_about_trailing_whitespace): AssertEqual \ [ \ ], - \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ ale#handlers#yamllint#Handle(bufnr(''), [ \ 'something.yml:5:18: [error] trailing spaces (trailing-spaces)', \ ]) From 4aa11cbc055ccbc18d2d48a944566b08d6815583 Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Fri, 15 May 2020 09:15:57 +0900 Subject: [PATCH 3/4] Improve documentation --- doc/ale-openapi.txt | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/doc/ale-openapi.txt b/doc/ale-openapi.txt index 27261de6..a1137ed8 100644 --- a/doc/ale-openapi.txt +++ b/doc/ale-openapi.txt @@ -15,7 +15,27 @@ Install ibm-openapi-validator either globally or locally: > npm install ibm-openapi-validator -g # global npm install ibm-openapi-validator # local < -Recommended plugin for openapi filetype detection: +Configuration +------------------------------------------------------------------------------- + +OpenAPI files can be written in YAML or JSON so in order for ALE plugins to +work with these files we must set the buffer |filetype| to either |openapi.yaml| +or |openapi.json| respectively. This causes ALE to lint the file with linters +configured for openapi and yaml files or openapi and json files respectively. + +For example setting filetype to |openapi.yaml| on a buffer and the following +|g:ale_linters| configuration will enable linting of openapi files using both +|ibm-validator| and |yamlint|: + +> + let g:ale_linters = { + \ 'yaml': ['yamllint'], + \ 'openapi': ['ibm-validator'] + \} +< + +The following plugin will detect openapi files automatically and set the +filetype to |openapi.yaml| or |openapi.json|: https://github.com/hsanson/vim-openapi From 9bc4b468c20e91350cf1a6d3739f91f504e230ed Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Fri, 22 Jan 2021 23:51:29 +0900 Subject: [PATCH 4/4] Fix linter error --- ale_linters/openapi/ibm_validator.vim | 2 +- doc/ale-openapi.txt | 6 +++--- doc/ale-supported-languages-and-tools.txt | 2 +- doc/ale.txt | 2 +- supported-tools.md | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ale_linters/openapi/ibm_validator.vim b/ale_linters/openapi/ibm_validator.vim index c54741d2..446931a2 100644 --- a/ale_linters/openapi/ibm_validator.vim +++ b/ale_linters/openapi/ibm_validator.vim @@ -51,7 +51,7 @@ function! ale_linters#openapi#ibm_validator#Handle(buffer, lines) abort endfunction call ale#linter#Define('openapi', { -\ 'name': 'ibm-validator', +\ 'name': 'ibm_validator', \ 'executable': {b -> ale#Var(b, 'openapi_ibm_validator_executable')}, \ 'command': function('ale_linters#openapi#ibm_validator#GetCommand'), \ 'callback': 'ale_linters#openapi#ibm_validator#Handle', diff --git a/doc/ale-openapi.txt b/doc/ale-openapi.txt index a1137ed8..1fc41add 100644 --- a/doc/ale-openapi.txt +++ b/doc/ale-openapi.txt @@ -2,7 +2,7 @@ ALE OpenApi Integration *ale-openapi-options* =============================================================================== -ibm-validator *ale-openapi-ibm-validator* +ibm_validator *ale-openapi-ibm-validator* Website: https://github.com/IBM/openapi-validator @@ -25,12 +25,12 @@ configured for openapi and yaml files or openapi and json files respectively. For example setting filetype to |openapi.yaml| on a buffer and the following |g:ale_linters| configuration will enable linting of openapi files using both -|ibm-validator| and |yamlint|: +|ibm_validator| and |yamlint|: > let g:ale_linters = { \ 'yaml': ['yamllint'], - \ 'openapi': ['ibm-validator'] + \ 'openapi': ['ibm_validator'] \} < diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 57eb71dc..13538b03 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -323,7 +323,7 @@ Notes: * `ocp-indent` * `ols` * OpenApi - * `ibm-validator` + * `ibm_validator` * `prettier` * `yamllint` * Pawn diff --git a/doc/ale.txt b/doc/ale.txt index b2cea4cd..cfb5beb4 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2836,7 +2836,7 @@ documented in additional help files. ocamlformat...........................|ale-ocaml-ocamlformat| ocp-indent............................|ale-ocaml-ocp-indent| openapi.................................|ale-openapi-options| - ibm-validator.........................|ale-openapi-ibm-validator| + ibm_validator.........................|ale-openapi-ibm-validator| prettier..............................|ale-openapi-prettier| yamllint..............................|ale-openapi-yamllint| pawn....................................|ale-pawn-options| diff --git a/supported-tools.md b/supported-tools.md index df9071f8..0cea2a1b 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -332,7 +332,7 @@ formatting. * [ocp-indent](https://github.com/OCamlPro/ocp-indent) * [ols](https://github.com/freebroccolo/ocaml-language-server) * OpenApi - * [ibm-validator](https://github.com/IBM/openapi-validator) + * [ibm_validator](https://github.com/IBM/openapi-validator) * [prettier](https://github.com/prettier/prettier) * [yamllint](https://yamllint.readthedocs.io/) * Pawn