Skip to content

Commit 2378263

Browse files
authored
fix: handle ts-type values with curly braces (#22)
1 parent 3c21f39 commit 2378263

File tree

6 files changed

+78
-5
lines changed

6 files changed

+78
-5
lines changed

bin/lint-markdown-ts-check.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import * as minimist from 'minimist';
99
import { rimraf } from 'rimraf';
1010
import { URI } from 'vscode-uri';
1111

12-
import { chunkFilenames, spawnAsync, wrapOrphanObjectInParens } from '../lib/helpers';
12+
import {
13+
chunkFilenames,
14+
findCurlyBracedDirectives,
15+
spawnAsync,
16+
wrapOrphanObjectInParens,
17+
} from '../lib/helpers';
1318
import { getCodeBlocks, DocsWorkspace } from '../lib/markdown';
1419

1520
interface Options {
@@ -82,9 +87,11 @@ async function main(workspaceRoot: string, globs: string[], { ignoreGlobs = [] }
8287
?.match(/\B@ts-ignore=\[([\d,]*)\]\B/)?.[1]
8388
.split(',')
8489
.map((line) => parseInt(line));
85-
const tsTypeLines = Array.from(
86-
codeBlock.meta?.matchAll(/\B@ts-type={([^:\r\n\t\f\v ]+):\s?([^}]+)}\B/g) ?? [],
87-
);
90+
const tsTypeLines = codeBlock.meta
91+
? findCurlyBracedDirectives('@ts-type', codeBlock.meta)
92+
.map((directive) => directive.match(/^([^:\r\n\t\f\v ]+):\s?(.+)$/))
93+
.filter((directive): directive is RegExpMatchArray => directive !== null)
94+
: [];
8895

8996
if (tsNoCheck && (tsExpectErrorLines || tsIgnoreLines || tsTypeLines.length)) {
9097
console.log(

lib/helpers.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as childProcess from 'node:child_process';
22
import * as os from 'node:os';
33

4+
import { range as balancedRange } from 'balanced-match';
5+
46
// Helper function to work around import issues with ESM module
57
// eslint-disable-next-line no-new-func
68
export const dynamicImport = new Function('specifier', 'return import(specifier)');
@@ -72,3 +74,23 @@ export function chunkFilenames(filenames: string[], offset: number = 0): string[
7274
[[]],
7375
);
7476
}
77+
78+
export function findCurlyBracedDirectives(directive: string, str: string) {
79+
const prefix = `${directive}=`;
80+
const matches: string[] = [];
81+
let idx = 0;
82+
83+
while (idx >= 0 && idx < str.length) {
84+
idx = str.indexOf(prefix, idx);
85+
if (idx >= 0) {
86+
idx = idx + prefix.length;
87+
const val = str.slice(idx);
88+
const range = balancedRange('{', '}', val);
89+
if (range) {
90+
matches.push(val.slice(range[0] + 1, range[1]).trim());
91+
}
92+
}
93+
}
94+
95+
return matches;
96+
}

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"devDependencies": {
4040
"@continuous-auth/semantic-release-npm": "^3.0.0",
4141
"@electron-internal/eslint-config": "^1.0.1",
42+
"@types/balanced-match": "^1.0.3",
4243
"@types/glob": "^8.0.1",
4344
"@types/jest": "^29.4.0",
4445
"@types/markdown-it": "^12.2.3",
@@ -55,6 +56,7 @@
5556
},
5657
"dependencies": {
5758
"@dsanders11/vscode-markdown-languageservice": "^0.3.0",
59+
"balanced-match": "^2.0.0",
5860
"glob": "^8.1.0",
5961
"markdown-it": "^13.0.1",
6062
"markdownlint-cli": "^0.33.0",

tests/fixtures/ts-check.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ window.myAwesomeAPI()
140140

141141
This block defines additional types
142142

143-
```js @ts-type={a: number} @ts-type={debug: (url: string) => boolean} @ts-type={b: number}
143+
```js @ts-type={a: number} @ts-type={anObject: { aProp: string }} @ts-type={debug: (url: string) => boolean} @ts-type={ anotherObject: { foo: { bar: string } } } @ts-type={b: number}
144144
if (a > b) {
145145
debug('true')
146146
} else {

tests/helpers.spec.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { findCurlyBracedDirectives } from '../lib/helpers';
2+
3+
describe('findCurlyBracedDirectives', () => {
4+
it('should return an empty array if no matches', () => {
5+
const matches = findCurlyBracedDirectives('foo', 'this is gibberish');
6+
expect(Array.isArray(matches)).toEqual(true);
7+
expect(matches.length).toEqual(0);
8+
});
9+
10+
it('should return a match when there is one match', () => {
11+
const matches = findCurlyBracedDirectives('@ts-type', '@ts-type={foo: string}');
12+
expect(Array.isArray(matches)).toEqual(true);
13+
expect(matches.length).toEqual(1);
14+
expect(matches[0]).toEqual('foo: string');
15+
});
16+
17+
it('should return a match when there are multiple matches', () => {
18+
const matches = findCurlyBracedDirectives(
19+
'@ts-type',
20+
'@ts-type={a: number} @ts-type={ anObject: { aProp: string } } @ts-type={debug: (url: string) => boolean} @ts-type={anObject: { foo: { bar: string } }} @ts-type={b: number}',
21+
);
22+
expect(Array.isArray(matches)).toEqual(true);
23+
expect(matches.length).toEqual(5);
24+
expect(matches).toEqual([
25+
'a: number',
26+
'anObject: { aProp: string }',
27+
'debug: (url: string) => boolean',
28+
'anObject: { foo: { bar: string } }',
29+
'b: number',
30+
]);
31+
});
32+
});

yarn.lock

+10
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,11 @@
933933
dependencies:
934934
"@babel/types" "^7.3.0"
935935

936+
"@types/balanced-match@^1.0.3":
937+
version "1.0.3"
938+
resolved "https://registry.yarnpkg.com/@types/balanced-match/-/balanced-match-1.0.3.tgz#14fd1e4175bc45b878ca310739b330d6748f5fd8"
939+
integrity sha512-nBZFt2r4snsIMicyNwgdga4wcoJtGRF39xX4Le3GjA2oSJcQlGAD8XrmlRddYcINFK8dypxJEUS6bVgKBQ7FyA==
940+
936941
"@types/debug@^4.0.0":
937942
version "4.1.7"
938943
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82"
@@ -1424,6 +1429,11 @@ balanced-match@^1.0.0:
14241429
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
14251430
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
14261431

1432+
balanced-match@^2.0.0:
1433+
version "2.0.0"
1434+
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9"
1435+
integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==
1436+
14271437
bin-links@^3.0.3:
14281438
version "3.0.3"
14291439
resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-3.0.3.tgz#3842711ef3db2cd9f16a5f404a996a12db355a6e"

0 commit comments

Comments
 (0)