Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pnpm check --fix
To enable checks for any of the following modules, just install them:

```sh
pnpm i -D typescript oxlint prettier publint eslint
pnpm i -D typescript oxlint prettier publint eslint markdownlint-cli
```

## Contributing
Expand All @@ -30,10 +30,14 @@ bun run build
# Run checks
bun check --help
bun check

# Debug commands used
DEBUG=1 bun check
```

### Adding Tools

I've added everything I use, so if you want to add support for another tool, feel free.

Just copy `src/tools/prettier.ts` and `src/tools/prettier.test.ts`, update the implementations (yes, tests are required), and add your new tool to `src/tools/index.ts`'s `ALL_TOOLS` export.
1. Copy and rename `src/tools/prettier.ts` and `src/tools/prettier.test.ts` accordingly
2. Implement and update tests for your new tool
3. Add your tool to the `ALL_TOOLS` array in `src/tools/index.ts`
4. Add the tool's NPM package to the first section of this README
10 changes: 9 additions & 1 deletion src/tools/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { eslint } from "./eslint";
import { markdownlint } from "./markdownlint";
import { oxlint } from "./oxlint";
import { prettier } from "./prettier";
import { publint } from "./publint";
import { typescript } from "./typescript";

export const ALL_TOOLS = [publint, prettier, typescript, oxlint, eslint];
export const ALL_TOOLS = [
eslint,
markdownlint,
oxlint,
prettier,
publint,
typescript,
];
74 changes: 74 additions & 0 deletions src/tools/markdownlint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { describe, it, expect } from "bun:test";
import { parseOutput } from "./markdownlint";

describe("Markdownlint", () => {
it("should properly parse output", async () => {
const stdout = "";
const stderr = `
[
{
"fileName": "docs/guide/resources/upgrading.md",
"lineNumber": 59,
"ruleNames": [
"MD031",
"blanks-around-fences"
],
"ruleDescription": "Fenced code blocks should be surrounded by blank lines",
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md031.md",
"errorDetail": null,
"errorContext": "\`\`\`ts",
"errorRange": null,
"fixInfo": {
"lineNumber": 59,
"insertText": "\\n"
}
},
{
"fileName": "CODE_OF_CONDUCT.md",
"lineNumber": 63,
"ruleNames": [
"MD034",
"no-bare-urls"
],
"ruleDescription": "Bare URL used",
"ruleInformation": "https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md034.md",
"errorDetail": null,
"errorContext": "example@gmail.com",
"errorRange": [
5,
23
],
"fixInfo": {
"editColumn": 1,
"deleteCount": 23,
"insertText": "<example@gmail.com>"
}
}
]
`;
const code = 1;

expect(parseOutput({ code, stdout, stderr })).toEqual([
{
file: "docs/guide/resources/upgrading.md",
message: "Fenced code blocks should be surrounded by blank lines",
location: {
line: 59,
column: 0,
},
rule: "MD031",
kind: "warning",
},
{
file: "CODE_OF_CONDUCT.md",
message: "Bare URL used",
location: {
line: 63,
column: 5,
},
rule: "MD034",
kind: "warning",
},
]);
});
});
40 changes: 40 additions & 0 deletions src/tools/markdownlint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { OutputParser, ToolDefinition } from "../types";
import { execAndParse } from "../utils";

export const markdownlint: ToolDefinition = ({ root }) => {
const bin = "markdownlint";
const checkArgs = [
".",
"--json",
"--ignore='**/dist/**'",
"--ignore='**/node_modules/**'",
"--ignore='**/.output/**'",
"--ignore='**/coverage/**'",
];
const fixArgs = [...checkArgs, "--fix"];

return {
name: "Markdownlint",
packageName: "markdownlint-cli",
check: () => execAndParse(bin, checkArgs, root, parseOutput),
fix: () => execAndParse(bin, fixArgs, root, parseOutput),
};
};

export const parseOutput: OutputParser = ({ stderr: _stderr }) => {
const stderr = _stderr.trim();

// When there are no errors, stderr is blank
if (!stderr) return [];

return JSON.parse(stderr).map((warning: any) => ({
location: {
line: warning.lineNumber,
column: warning.errorRange?.[0] ?? 0,
},
message: warning.ruleDescription,
file: warning.fileName,
kind: "warning",
rule: warning.ruleNames[0],
}));
};