Skip to content

Commit 110b288

Browse files
feat: parse class descriptions (#25)
* feat: parse class descriptions * spec: add tests for code fence parsing * feat: parse module descriptions
1 parent 2470a9c commit 110b288

File tree

4 files changed

+96
-6
lines changed

4 files changed

+96
-6
lines changed

src/DocsParser.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ import {
2424
findConstructorHeader,
2525
consumeTypedKeysList,
2626
findProcess,
27+
getContentBeforeConstructor,
28+
findContentAfterHeadingClose,
29+
HeadingContent,
30+
getContentBeforeFirstHeadingMatching,
2731
} from './markdown-helpers';
2832
import { WEBSITE_BASE_DOCS_URL, REPO_BASE_DOCS_URL } from './constants';
2933
import { extendError } from './helpers';
@@ -94,7 +98,26 @@ export class DocsParser {
9498
if (isStructure) {
9599
description = safelyJoinTokens(findContentAfterList(tokens));
96100
} else {
97-
// TODO: Pull the top level Module / Class description
101+
let groups: HeadingContent[];
102+
if (isClass) {
103+
groups = getContentBeforeConstructor(tokens);
104+
} else {
105+
// FIXME: Make it so that we don't need this magic FIXME for the electron breaking-changes document
106+
groups = getContentBeforeFirstHeadingMatching(tokens, heading =>
107+
['Events', 'Methods', 'Properties', '`FIXME` comments'].includes(heading.trim()),
108+
);
109+
}
110+
description = groups
111+
.map((group, index) => {
112+
const inner = safelyJoinTokens(findContentAfterHeadingClose(group.content), {
113+
parseCodeFences: true,
114+
});
115+
if (index !== 0) {
116+
return `### ${group.heading}\n\n${inner}`;
117+
}
118+
return inner;
119+
})
120+
.join('\n\n');
98121
}
99122

100123
const extendsMatch = / Object extends `(.+?)`?$/.exec(heading.heading);

src/__tests__/__snapshots__/markdown-helpers.spec.ts.snap

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,18 @@ exports[`markdown-helpers safelyJoinTokens snapshots should be correct for parag
334334
exports[`markdown-helpers safelyJoinTokens snapshots should be correct for paragraph-with-links 1`] = `"This paragraph has a bunch of stuff. Also some links Foo, these links should be stripped."`;
335335

336336
exports[`markdown-helpers safelyJoinTokens snapshots should be correct for paragraph-with-text-markers 1`] = `"Heya, this is **bold** and _italic_ and *italic* and ~~struck through~~"`;
337+
338+
exports[`markdown-helpers safelyJoinTokens with code fence support should correctly insert the code fence 1`] = `
339+
"> a
340+
341+
\`\`\`
342+
wat
343+
344+
def fn():
345+
pass
346+
347+
# a
348+
\`\`\`
349+
350+
> foo"
351+
`;

src/__tests__/markdown-helpers.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,28 @@ describe('markdown-helpers', () => {
6767
});
6868
}
6969
});
70+
71+
describe('with code fence support', () => {
72+
it('should correctly insert the code fence', () => {
73+
const tokens = getTokens(
74+
`
75+
> a
76+
77+
\`\`\`
78+
wat
79+
80+
def fn():
81+
pass
82+
83+
# a
84+
\`\`\`
85+
86+
> foo
87+
`,
88+
);
89+
expect(safelyJoinTokens(tokens, { parseCodeFences: true })).toMatchSnapshot();
90+
});
91+
});
7092
});
7193

7294
describe('extractStringEnum()', () => {

src/markdown-helpers.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,36 @@ export const headingsAndContent = (tokens: Token[]): HeadingContent[] => {
139139
return groups;
140140
};
141141

142+
const getConstructorHeaderInGroups = (groups: HeadingContent[]) => {
143+
return groups.find(group => group.heading.startsWith('`new ') && group.level === 3);
144+
};
145+
142146
export const findConstructorHeader = (tokens: Token[]) => {
143147
const groups = headingsAndContent(tokens);
144-
const constructorHeader = groups.find(
145-
group => group.heading.startsWith('`new ') && group.level === 3,
146-
);
148+
const constructorHeader = getConstructorHeaderInGroups(groups);
147149
return constructorHeader ? constructorHeader : null;
148150
};
149151

152+
export const getContentBeforeConstructor = (tokens: Token[]) => {
153+
const groups = headingsAndContent(tokens);
154+
const constructorHeader = getConstructorHeaderInGroups(groups);
155+
if (!constructorHeader) return [];
156+
157+
return groups.slice(0, groups.indexOf(constructorHeader));
158+
};
159+
160+
export const getContentBeforeFirstHeadingMatching = (
161+
tokens: Token[],
162+
matcher: (heading: string) => boolean,
163+
) => {
164+
const groups = headingsAndContent(tokens);
165+
166+
return groups.slice(
167+
0,
168+
groups.findIndex(g => matcher(g.heading)),
169+
);
170+
};
171+
150172
export const findContentInsideHeader = (
151173
tokens: Token[],
152174
expectedHeader: string,
@@ -461,13 +483,17 @@ export const extractReturnType = (
461483
};
462484
};
463485

486+
export interface JoinTokenOptions {
487+
parseCodeFences?: boolean;
488+
}
489+
464490
// NOTE: This method obliterates code fences
465-
export const safelyJoinTokens = (tokens: Token[]) => {
491+
export const safelyJoinTokens = (tokens: Token[], options: JoinTokenOptions = {}) => {
466492
let joinedContent = '';
467493
let listLevel = -1;
468494
for (const tokenToCheck of tokens) {
469495
if (tokenToCheck.children !== null && tokenToCheck.type === 'inline') {
470-
joinedContent += safelyJoinTokens(tokenToCheck.children);
496+
joinedContent += safelyJoinTokens(tokenToCheck.children, options);
471497
continue;
472498
}
473499
expect(tokenToCheck.children).to.equal(
@@ -557,7 +583,11 @@ export const safelyJoinTokens = (tokens: Token[]) => {
557583
break;
558584
case 'paragraph_open':
559585
case 'blockquote_close':
586+
break;
560587
case 'fence':
588+
if (options.parseCodeFences) {
589+
joinedContent += `\`\`\`\n${tokenToCheck.content}\`\`\`\n\n`;
590+
}
561591
break;
562592
default:
563593
expect(false).to.equal(true, 'unreachable default switch case');

0 commit comments

Comments
 (0)