A powerfull linter for projects architecture written in rust.
OBS: This is a project i made mostly for fun and to learn rust, so it's not production ready and probably is not following the best practices haha. So advices, suggestions and issues are welcome!!
OBS2: Although the project goal is to lint any project of any stack, for now it's mostly focused on typescript projects.
pnpm add -D palinter
# or
yarn add -D palinter
# or
npm install -D palinter
To understand the basics of how to use the linter, let's create a simple project to lint a folder with svg files.
The project structure will be:
.
└── images
├── file1.svg
├── file2.svg
└── file3.svg
The goal is to validate if all files in the svgFolder have the extension .svg
and are named in camelCase.
First let's create a config file to validate the project.
Create a file named palinter.yaml
in the root of your project.
In this file we first select the folder we want to validate and then add the rules to validate the files inside it:
# select the root folder
./:
# select the ./images folder
/images:
# add the rules
rules:
- if_file: any
expect:
extension_is: svg
Each rule is composed of a condition (if_file
or if_folder
) and assertions (what we expect
to happen) to be checket if the condition is met. In this case:
rules:
# the `expect` will be applied to any file in the folder
- if_file: any
expect:
# the file extension should be `svg`
extension_is: svg
Now let's add a new rule to ensure that the files are named in camelCase:
./:
/images:
rules:
- if_file: any
expect:
extension_is: svg
# + the file name should be in camelCase
name_case_is: camelCase
I'ts all set! Now let's run the linter. In terminal run:
pnpm exec palinter
Now let's add .png files to the folder and validate if they are named in kebab-case
:
./:
/images:
rules:
- if_file:
# this rule will be applied only to files with the extension `svg`
has_extension: svg
expect:
name_case_is: camelCase
- if_file:
# this rule will be applied only to files with the extension `png`
has_extension: png
expect:
name_case_is: kebab-case
By adding conditions we can have fine control over what rules will be applied to each file. If some file doesn't match any condition, it will be reported as an error to ensure that all files are validated.
This is the basic of how to use the linter. There are a lot of other conditions and rules that can be used to validate advanced project structures.
TODO
Check the test_cases folder for examples for now
TODO
Check the test_cases folder for examples for now
TODO
Apply the rule to any file
- if_file: any
Check if the file has the specified extension
- if_file:
has_extension: svg
# can also be a list of extensions
has_extension:
- svg
- png
Check if the file name matches the specified pattern
- if_file:
has_name: file.svg
# the pattern can be a glob pattern
has_name: file*.svg
Check if the file name doesn't match the specified pattern
- if_file:
not_has_name: file.svg
# the pattern can be a glob pattern
not_has_name: file*.svg
Check if the file is a typescript file
- if_file:
is_ts: true
Apply the rule to any folder
- if_folder: any
Check if the folder name is in the specified case
- if_folder:
has_name_case: camelCase # or: kebab-case, snake_case, PascalCase
Check if the folder name matches the specified pattern
- if_folder:
has_name: folder
# the pattern can be a glob pattern
has_name: folder*
Check if the folder name doesn't match the specified pattern
- if_folder:
not_has_name: folder
# the pattern can be a glob pattern
not_has_name: folder*
Check if the folder has files in it's root that match the specified pattern. The captured groups in the pattern can be used in the assertions.
- if_folder:
root_files_find_pattern:
# the pattern can be a glob pattern
pattern: '*.test.ts'
# OR a regex
pattern: regex:(Foo|Bar)*
# limit the number of files that should match the pattern
at_least: 1
at_most: 1
Asserts that the file name is in the specified case
- if_file: any
expect:
name_case_is: camelCase
Asserts that the file extension is the specified
- if_file: any
expect:
extension_is: svg
# can also be a list of extensions
extension_is:
- svg
- png
Asserts that the file name matches the specified pattern
- if_file: any
expect:
name_is: file.svg
# the pattern can be a glob pattern
name_is: file*.svg
Asserts that the file name doesn't match the specified pattern
- if_file: any
expect:
name_is_not: file.svg
# the pattern can be a glob pattern
name_is_not: file*.svg
Asserts that the file is not empty
- if_file: any
expect:
is_not_empty: true
Asserts that the file content matches the specified pattern
- if_file: any
expect:
content_matches: Hello World
You can also specify a list of patterns to match:
# assert that the file content matches any of the patterns
content_matches:
- any:
- Bar
- Foo
# the patterns should be matched at most 1 time
at_most: 1
# the patterns should be matched at least 1 time
at_least: 1
Match all patterns:
# assert that the file content matches all of the patterns
content_matches:
- all:
- Bar
- Foo
# all the patterns should be matched at most 1 time
at_most: 1
# all the patterns should be matched at least 1 time
at_least: 1
You can also use regex in the patterns:
# assert that the file content matches the regex
content_matches: regex:(Foo|Bar)*
You can use context variables from conditions and parent rules in the patterns:
- if_file:
has_name: '*.test.tsx'
expect:
content_matches: export const ${1}
# ${1} will be replaced by the value of the first capture group in the has_name pattern