Skip to content

Commit 26875df

Browse files
committed
lint(format): scripts
1 parent 3fc7dd8 commit 26875df

File tree

3 files changed

+96
-54
lines changed

3 files changed

+96
-54
lines changed

scripts/checkLinks.mjs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
55
const __filename = fileURLToPath(import.meta.url);
66
const __dirname = path.dirname(__filename);
77

8-
const extractLinks = (content) => {
8+
const extractLinks = content => {
99
const noSingleLineComments = content.replace(/\/\/.*$/gm, '');
1010
const noComments = noSingleLineComments.replace(/\/\*[\s\S]*?\*\//g, '');
1111
const linkRegex = /link:\s*(['"])([^'"]+)\1/g;
@@ -15,17 +15,17 @@ const extractLinks = (content) => {
1515
links.push(match[2]);
1616
}
1717
return links;
18-
}
18+
};
1919

20-
const fileExists = (filePath) => {
20+
const fileExists = filePath => {
2121
try {
2222
return fs.existsSync(filePath);
2323
} catch (err) {
2424
return false;
2525
}
26-
}
26+
};
2727

28-
const checkLink = (link) => {
28+
const checkLink = link => {
2929
if (link.startsWith('http')) {
3030
return true;
3131
}
@@ -46,10 +46,16 @@ const checkLink = (link) => {
4646
}
4747

4848
return false;
49-
}
49+
};
5050

51-
const navContent = fs.readFileSync(path.join(__dirname, '../main/.vitepress/themeConfig/nav.js'), 'utf8');
52-
const configContent = fs.readFileSync(path.join(__dirname, '../main/.vitepress/config.mjs'), 'utf8');
51+
const navContent = fs.readFileSync(
52+
path.join(__dirname, '../main/.vitepress/themeConfig/nav.js'),
53+
'utf8',
54+
);
55+
const configContent = fs.readFileSync(
56+
path.join(__dirname, '../main/.vitepress/config.mjs'),
57+
'utf8',
58+
);
5359

5460
const navLinks = extractLinks(navContent);
5561
const configLinks = extractLinks(configContent);

scripts/format.mjs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { exec } from 'child_process';
22

3-
exec('node scripts/markdown-js-snippets-linter.mjs "main/**/*.md" && prettier --check "**/*.md" --config .prettierrc.json', (err, stdout, stderr) => {
4-
if (err) {
5-
const modifiedStderr = stderr.replace(
6-
'Run Prettier with --write to fix',
7-
'Run `yarn format` to fix'
8-
);
9-
console.warn(modifiedStderr);
10-
process.exit(1);
11-
}
12-
});
3+
exec(
4+
'node scripts/markdown-js-snippets-linter.mjs "main/**/*.md" && prettier --check "**/*.md" --config .prettierrc.json',
5+
(err, stdout, stderr) => {
6+
if (err) {
7+
const modifiedStderr = stderr.replace(
8+
'Run Prettier with --write to fix',
9+
'Run `yarn format` to fix',
10+
);
11+
console.warn(modifiedStderr);
12+
process.exit(1);
13+
}
14+
},
15+
);

scripts/markdown-js-snippets-linter.mjs

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import {promises as fs} from 'fs';
1+
import { promises as fs } from 'fs';
22
import glob from 'glob';
33
import util from 'util';
44

55
const globPromise = util.promisify(glob);
66

7-
const extractJsSnippets = (markdownContent) => {
7+
const extractJsSnippets = markdownContent => {
88
const pattern = /```(?:js|javascript)\n([\s\S]*?)```/g;
99
const matches = [];
1010
let match;
@@ -15,7 +15,7 @@ const extractJsSnippets = (markdownContent) => {
1515
start: match.index,
1616
end: match.index + match[0].length,
1717
startLine: startLine,
18-
language: match[0].startsWith('```javascript') ? 'javascript' : 'js'
18+
language: match[0].startsWith('```javascript') ? 'javascript' : 'js',
1919
});
2020
}
2121
return matches;
@@ -29,17 +29,22 @@ const checkSemicolonsAndEllipsis = (code, startLine) => {
2929
let openSquareBrackets = 0;
3030
let inMultiLineComment = false;
3131

32-
const isJSDocOrComment = (line) => {
33-
return line.trim().startsWith('*') ||
32+
const isJSDocOrComment = line => {
33+
return (
34+
line.trim().startsWith('*') ||
3435
line.trim().startsWith('/**') ||
3536
line.trim().startsWith('*/') ||
36-
line.trim().startsWith('//');
37+
line.trim().startsWith('//')
38+
);
3739
};
3840

3941
const isStatementEnd = (line, nextLine) => {
4042
const strippedLine = line.replace(/\/\/.*$/, '').trim();
41-
const strippedNextLine = nextLine ? nextLine.replace(/\/\/.*$/, '').trim() : '';
42-
return strippedLine &&
43+
const strippedNextLine = nextLine
44+
? nextLine.replace(/\/\/.*$/, '').trim()
45+
: '';
46+
return (
47+
strippedLine &&
4348
!strippedLine.endsWith('{') &&
4449
!strippedLine.endsWith('}') &&
4550
!strippedLine.endsWith(':') &&
@@ -61,19 +66,25 @@ const checkSemicolonsAndEllipsis = (code, startLine) => {
6166
!strippedNextLine.trim().startsWith('.finally') &&
6267
openBrackets === 0 &&
6368
openParens === 0 &&
64-
openSquareBrackets === 0;
69+
openSquareBrackets === 0
70+
);
6571
};
6672

6773
const shouldHaveSemicolon = (line, nextLine) => {
6874
const strippedLine = line.replace(/\/\/.*$/, '').trim();
69-
return (strippedLine.startsWith('const ') ||
70-
strippedLine.startsWith('let ') ||
71-
strippedLine.startsWith('var ') ||
72-
strippedLine.includes('=') ||
73-
/\bawait\b/.test(strippedLine) ||
74-
(/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(strippedLine) && !strippedLine.endsWith('.')) ||
75-
(/^[a-zA-Z_$][a-zA-Z0-9_$]*\[[0-9]+\]$/.test(strippedLine))) &&
76-
isStatementEnd(line, nextLine);
75+
return (
76+
(strippedLine.startsWith('const ') ||
77+
strippedLine.startsWith('let ') ||
78+
strippedLine.startsWith('var ') ||
79+
strippedLine.includes('=') ||
80+
/\bawait\b/.test(strippedLine) ||
81+
(/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(
82+
strippedLine,
83+
) &&
84+
!strippedLine.endsWith('.')) ||
85+
/^[a-zA-Z_$][a-zA-Z0-9_$]*\[[0-9]+\]$/.test(strippedLine)) &&
86+
isStatementEnd(line, nextLine)
87+
);
7788
};
7889

7990
for (let i = 0; i < lines.length; i++) {
@@ -87,9 +98,12 @@ const checkSemicolonsAndEllipsis = (code, startLine) => {
8798
}
8899
if (inMultiLineComment || isJSDocOrComment(line)) continue;
89100

90-
openBrackets += (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
91-
openParens += (line.match(/\(/g) || []).length - (line.match(/\)/g) || []).length;
92-
openSquareBrackets += (line.match(/\[/g) || []).length - (line.match(/\]/g) || []).length;
101+
openBrackets +=
102+
(line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
103+
openParens +=
104+
(line.match(/\(/g) || []).length - (line.match(/\)/g) || []).length;
105+
openSquareBrackets +=
106+
(line.match(/\[/g) || []).length - (line.match(/\]/g) || []).length;
93107

94108
const codeWithoutComment = line.replace(/\/\/.*$/, '').trim();
95109

@@ -99,22 +113,24 @@ const checkSemicolonsAndEllipsis = (code, startLine) => {
99113
line: startLine + i,
100114
original: line.trim(),
101115
fixed: '// ...',
102-
type: 'ellipsis'
116+
type: 'ellipsis',
103117
});
104-
} else if (shouldHaveSemicolon(line, nextLine) && !codeWithoutComment.endsWith(';')) {
118+
} else if (
119+
shouldHaveSemicolon(line, nextLine) &&
120+
!codeWithoutComment.endsWith(';')
121+
) {
105122
issues.push({
106123
line: startLine + i,
107124
original: line.trim(),
108125
fixed: `${codeWithoutComment};${line.includes('//') ? ' ' + line.split('//')[1] : ''}`,
109-
type: 'semicolon'
126+
type: 'semicolon',
110127
});
111128
}
112129
}
113130

114131
return issues;
115132
};
116133

117-
118134
const lintMarkdownFile = async (filePath, fix = false) => {
119135
try {
120136
const content = await fs.readFile(filePath, 'utf8');
@@ -124,7 +140,10 @@ const lintMarkdownFile = async (filePath, fix = false) => {
124140

125141
for (let i = jsSnippets.length - 1; i >= 0; i--) {
126142
const snippet = jsSnippets[i];
127-
const issues = checkSemicolonsAndEllipsis(snippet.content, snippet.startLine);
143+
const issues = checkSemicolonsAndEllipsis(
144+
snippet.content,
145+
snippet.startLine,
146+
);
128147
allIssues.push(...issues.map(issue => ({ ...issue, snippet: i + 1 })));
129148

130149
if (fix) {
@@ -134,8 +153,11 @@ const lintMarkdownFile = async (filePath, fix = false) => {
134153
fixedLines[lineIndex] = issue.fixed;
135154
});
136155
const fixedSnippet = fixedLines.join('\n');
137-
fixedContent = fixedContent.slice(0, snippet.start) +
138-
'```js\n' + fixedSnippet + '```' +
156+
fixedContent =
157+
fixedContent.slice(0, snippet.start) +
158+
'```js\n' +
159+
fixedSnippet +
160+
'```' +
139161
fixedContent.slice(snippet.end);
140162
}
141163
}
@@ -156,7 +178,7 @@ const lintMarkdownFile = async (filePath, fix = false) => {
156178
filePath,
157179
issues: allIssues,
158180
fixedContent: fix ? fixedContent : null,
159-
javascriptCount: javascriptCount
181+
javascriptCount: javascriptCount,
160182
};
161183
} catch (error) {
162184
console.error(`Error processing file ${filePath}: ${error.message}`);
@@ -176,7 +198,10 @@ const processFiles = async (globPattern, fix = false) => {
176198
let hasErrors = false;
177199

178200
for (const file of files) {
179-
const { issues, error, javascriptCount } = await lintMarkdownFile(file, fix);
201+
const { issues, error, javascriptCount } = await lintMarkdownFile(
202+
file,
203+
fix,
204+
);
180205
if (error) {
181206
console.error(`\nError in file ${file}:`);
182207
console.error(error);
@@ -187,13 +212,17 @@ const processFiles = async (globPattern, fix = false) => {
187212
issues.forEach(issue => {
188213
console.error(`\nSnippet ${issue.snippet}, Line ${issue.line}:`);
189214
console.error(`Original: ${issue.original}`);
190-
console.error(`${fix ? 'Fixed: ' : 'Suggested:'} ${issue.fixed}`);
215+
console.error(
216+
`${fix ? 'Fixed: ' : 'Suggested:'} ${issue.fixed}`,
217+
);
191218
});
192219
totalIssues += issues.length;
193220
hasErrors = true;
194221
}
195222
if (javascriptCount > 0) {
196-
console.error(`\nFound ${javascriptCount} instance(s) of \`\`\`javascript in ${file}`);
223+
console.error(
224+
`\nFound ${javascriptCount} instance(s) of \`\`\`javascript in ${file}`,
225+
);
197226
totalJavascriptInstances += javascriptCount;
198227
hasErrors = true;
199228
}
@@ -202,14 +231,18 @@ const processFiles = async (globPattern, fix = false) => {
202231

203232
if (totalIssues > 0 || totalJavascriptInstances > 0) {
204233
console.error(`\nTotal errors found: ${totalIssues}`);
205-
console.error(`Total \`\`\`javascript instances found: ${totalJavascriptInstances}`);
234+
console.error(
235+
`Total \`\`\`javascript instances found: ${totalJavascriptInstances}`,
236+
);
206237
if (fix) {
207-
console.log("All matching files have been updated with the necessary changes.");
238+
console.log(
239+
'All matching files have been updated with the necessary changes.',
240+
);
208241
} else {
209-
console.error("Run `yarn format` to automatically fix these errors");
242+
console.error('Run `yarn format` to automatically fix these errors');
210243
}
211244
} else {
212-
console.log("No errors found in any of the matching files.");
245+
console.log('No errors found in any of the matching files.');
213246
}
214247

215248
if (hasErrors && !fix) {
@@ -223,7 +256,7 @@ const processFiles = async (globPattern, fix = false) => {
223256

224257
const main = async () => {
225258
if (process.argv.length < 3 || process.argv.length > 4) {
226-
console.error("Usage: node linter.js <glob_pattern> [--fix]");
259+
console.error('Usage: node linter.js <glob_pattern> [--fix]');
227260
process.exit(1);
228261
}
229262

0 commit comments

Comments
 (0)