Skip to content

Commit d763f57

Browse files
Merge pull request #17 from HackYourFuture-CPH/linting-tasks
lint: source location reporting, "watch", and VS Code tasks
2 parents 70c3d51 + 986661d commit d763f57

File tree

13 files changed

+305
-156
lines changed

13 files changed

+305
-156
lines changed

.github/workflows/lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
steps:
2020
- name: Checkout code
2121
uses: actions/checkout@v4
22-
- name: npm install
23-
run: npm install
22+
- name: Compile
23+
run: npm install && npm run build
2424
- name: Run the linter
2525
run: ./lint

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# Ignore hidden Mac OS directory files
22
**/.DS_Store
33
node_modules/
4+
support/dist/

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
/dist/
1+
/support/dist/

.vscode/tasks.json

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
{
2+
// See https://go.microsoft.com/fwlink/?LinkId=733558
3+
// for the documentation about the tasks.json format
4+
"version": "2.0.0",
5+
"tasks": [
6+
{
7+
"label": "./lint",
8+
"detail": "Runs all supplied linters. This is the same check that runs on all pull requests.",
9+
"type": "npm",
10+
"script": "lint",
11+
"problemMatcher": {
12+
"fileLocation": ["relative", "${workspaceFolder}"],
13+
"severity": "error",
14+
"owner": "lint-owner",
15+
"source": "lint-source",
16+
"pattern": {
17+
"regexp": "^(.*?):(\\d+)(?::(\\d+))? ((?:MD|VL)\\S+) (.*)$",
18+
"file": 1,
19+
"line": 2,
20+
"column": 3,
21+
"code": 4,
22+
"message": 5
23+
}
24+
}
25+
},
26+
{
27+
"label": "./lint (watch)",
28+
"detail": "Runs all linters. This is the same check that runs on all pull requests.",
29+
"type": "npm",
30+
"script": "lint:watch",
31+
"isBackground": true,
32+
"problemMatcher": {
33+
"fileLocation": ["relative", "${workspaceFolder}"],
34+
"severity": "error",
35+
"owner": "lint-owner",
36+
"source": "lint-source",
37+
"pattern": {
38+
"regexp": "^(.*?):(\\d+)(?::(\\d+))? ((?:MD|VL)\\S+) (.*)$",
39+
"file": 1,
40+
"line": 2,
41+
"column": 3,
42+
"code": 4,
43+
"message": 5
44+
},
45+
"background": {
46+
"activeOnStart": true,
47+
"beginsPattern": "^lint: RUN$",
48+
"endsPattern": "^lint: (PASS|FAIL)$"
49+
}
50+
}
51+
},
52+
{
53+
"label": "./lint validate-links",
54+
"detail": "Check markdown for broken internal links & images",
55+
"type": "npm",
56+
"script": "lint:validate-links",
57+
"problemMatcher": {
58+
"fileLocation": ["relative", "${workspaceFolder}"],
59+
"severity": "error",
60+
"owner": "lint-owner",
61+
"source": "lint-source",
62+
"pattern": {
63+
"regexp": "^(.*?):(\\d+)(?::(\\d+))? ((?:MD|VL)\\S+) (.*)$",
64+
"file": 1,
65+
"line": 2,
66+
"column": 3,
67+
"code": 4,
68+
"message": 5
69+
}
70+
}
71+
},
72+
{
73+
"label": "./lint validate-links (watch)",
74+
"detail": "Check markdown for broken internal links & images",
75+
"type": "npm",
76+
"script": "lint:validate-links:watch",
77+
"isBackground": true,
78+
"problemMatcher": {
79+
"fileLocation": ["relative", "${workspaceFolder}"],
80+
"severity": "error",
81+
"owner": "lint-owner",
82+
"source": "lint-source",
83+
"pattern": {
84+
"regexp": "^(.*?):(\\d+)(?::(\\d+))? ((?:MD|VL)\\S+) (.*)$",
85+
"file": 1,
86+
"line": 2,
87+
"column": 3,
88+
"code": 4,
89+
"message": 5
90+
},
91+
"background": {
92+
"activeOnStart": true,
93+
"beginsPattern": "^validate-links: RUN$",
94+
"endsPattern": "^validate-links: (PASS|FAIL)$"
95+
}
96+
}
97+
}
98+
]
99+
}

dist/parse.js

Lines changed: 0 additions & 35 deletions
This file was deleted.

dist/validateLinks.js

Lines changed: 0 additions & 80 deletions
This file was deleted.

lint

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,58 @@
22

33
set -eu
44

5-
if [ "${1:-}" == "--fix" ] ; then
6-
npm exec -- markdownlint --ignore 'node_modules/' --fix '**/*.md'
7-
npm exec -- prettier --write .
8-
else
9-
trap '
10-
if [ $? -ne 0 ] ; then
11-
echo "Try '\''./lint --fix'\'' to see if any automatic fixes are possible"
5+
validate-links() {
6+
echo "validate-links: RUN"
7+
if npm exec -- node support/dist/validateLinks.js ; then
8+
echo validate-links: PASS
9+
else
10+
echo validate-links: FAIL
11+
return 1
1212
fi
13-
' 0
13+
}
1414

15-
rc=0
16-
17-
echo "validateLinks: ..."
18-
if npm exec -- node dist/validateLinks.js ; then
19-
echo validateLinks: PASS
20-
else
21-
echo validateLinks: FAIL
22-
rc=1
23-
fi
24-
25-
echo "markdownlint: ..."
15+
markdownlint() {
16+
echo "markdownlint: RUN"
2617
if npm exec -- markdownlint --ignore 'node_modules/' '**/*.md' ; then
2718
echo "markdownlint: PASS"
2819
else
2920
echo "markdownlint: FAIL"
30-
rc=1
21+
return 1
3122
fi
23+
}
3224

33-
echo "prettier: ..."
25+
prettier() {
26+
echo "prettier: RUN"
3427
if npm exec -- prettier --check . ; then
3528
echo "prettier: PASS"
3629
else
3730
echo "prettier: FAIL"
38-
rc=1
31+
return 1
3932
fi
33+
}
34+
35+
all() {
36+
local rc=0
37+
echo "lint: RUN"
38+
validate-links || rc=1
39+
markdownlint || rc=1
40+
prettier || rc=1
4041

41-
exit $rc
42+
if [ $rc -eq 0 ] ; then
43+
echo "lint: PASS"
44+
else
45+
echo "lint: FAIL"
46+
echo "Try './lint --fix' to see if any automatic fixes are possible"
47+
fi
48+
49+
return $rc
50+
}
51+
52+
if [ "${1:-}" == "--fix" ] ; then
53+
npm exec -- markdownlint --ignore 'node_modules/' --fix '**/*.md' || :
54+
npm exec -- prettier --write . || :
55+
elif [ "${1:-}" == "validate-links" ] ; then
56+
validate-links
57+
else
58+
all
4259
fi

package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,13 @@
88
"@types/markdown-it": "^14.1.2",
99
"@types/node": "^22.14.1",
1010
"typescript": "^5.8.3"
11+
},
12+
"scripts": {
13+
"build": "tsc -p support/tsconfig.json",
14+
"lint": "./lint",
15+
"lint:fix": "./lint --fix",
16+
"lint:validate-links": "./lint validate-links",
17+
"lint:validate-links:watch": "node support/dist/watch.js ./lint validate-links",
18+
"lint:watch": "node support/dist/watch.js ./lint"
1119
}
1220
}

parse.ts renamed to support/src/parse.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import mit from "markdown-it";
22
import type { Token } from "markdown-it/index.js";
3+
import { sourceLocationOf, type SourceLocation } from "./sourceLocation.js";
34

45
export type ParsedLink = {
56
readonly target: string;
67
readonly content: string;
8+
readonly sourceLocation: SourceLocation | null;
79
};
810

911
export type ParsedImage = {
1012
readonly src: string;
1113
readonly alt: string;
14+
readonly sourceLocation: SourceLocation | null;
1215
};
1316

1417
export type ParseResult = {
@@ -31,21 +34,26 @@ export const parse = (content: string): ParseResult => {
3134
);
3235

3336
if (indexOfNextClose > index) {
37+
const target = token.attrGet("href") as string;
3438
parsedLinks.push({
35-
target: token.attrGet("href") as string,
39+
target,
3640
content: tokens
3741
.slice(index + 1, indexOfNextClose)
3842
.map((t) => t.content)
3943
.join(""),
44+
sourceLocation: sourceLocationOf(`(${target})`, content),
4045
});
4146
}
4247
}
4348

44-
if (token.type === "image")
49+
if (token.type === "image") {
50+
const src = token.attrGet("src") as string;
4551
parsedImages.push({
46-
src: token.attrGet("src") as string,
52+
src,
4753
alt: token.content,
54+
sourceLocation: sourceLocationOf(`(${src})`, content),
4855
});
56+
}
4957

5058
if (token.children) scan(token.children);
5159
});

0 commit comments

Comments
 (0)