-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathprocedure-page.ts
More file actions
127 lines (116 loc) · 3.35 KB
/
procedure-page.ts
File metadata and controls
127 lines (116 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import {
extractProcedureComments,
resolveTypeLink,
resolveTypeName,
} from '../extractors';
import { type ProcedurePageProps } from '../types';
import {
breadcrumbs,
generatedHeader,
navigationFooter,
referencesSection,
renderSourceAndDeclaration,
sectionHeading,
} from './common';
import { type Procedure } from '@zenstackhq/language/ast';
/**
* Renders a full documentation page for a procedure declaration.
*/
export function renderProcedurePage(props: ProcedurePageProps): string {
return [
...renderHeader(props),
...renderProcDescription(props.proc),
...renderSourceAndDeclaration(props.proc, props.options.schemaDir),
...renderParametersSection(props.proc),
...renderReturnsSection(props.proc),
...renderFlowDiagram(props.proc),
...referencesSection('procedure'),
...navigationFooter(props.navigation),
].join('\n');
}
/**
* Renders a Mermaid flowchart showing parameter inputs flowing through the procedure to its return type.
*/
function renderFlowDiagram(proc: Procedure): string[] {
const lines = ['```mermaid', 'flowchart LR'];
const procNodeId = `proc["${proc.name}"]`;
if (proc.params.length > 0) {
for (const parameter of proc.params) {
const typeName = resolveTypeName(parameter.type);
const suffix = parameter.optional ? '?' : '';
const arrayMark = parameter.type.array ? '[]' : '';
lines.push(
` ${parameter.name}["${parameter.name}: ${typeName}${arrayMark}${suffix}"] --> ${procNodeId}`,
);
}
} else {
lines.push(` input((" ")) --> ${procNodeId}`);
}
const returnValueTypeName = resolveTypeName(proc.returnType);
const retArray = proc.returnType.array ? '[]' : '';
lines.push(` ${procNodeId} --> ret["${returnValueTypeName}${retArray}"]`);
lines.push('```', '');
return lines;
}
/**
* Renders the page header with breadcrumb and mutation/query badge.
*/
function renderHeader(props: ProcedurePageProps): string[] {
return [
...generatedHeader(
props.options.genCtx,
props.options.includeGeneratedHeader,
),
breadcrumbs('Procedures', props.proc.name, '../'),
'',
`# ${props.proc.name} <kbd>${props.proc.mutation ? 'Mutation' : 'Query'}</kbd>`,
'',
];
}
/**
* Renders the procedure's parameters as a name/type/required table.
*/
function renderParametersSection(proc: Procedure): string[] {
if (proc.params.length === 0) {
return [];
}
const lines = [
...sectionHeading('Parameters'),
'',
'| Parameter | Type | Required |',
'| --- | --- | --- |',
];
for (const parameter of proc.params) {
lines.push(
`| \`${parameter.name}\` | ${resolveTypeLink(parameter.type, true)} | ${parameter.optional ? 'No' : 'Yes'} |`,
);
}
lines.push('');
return lines;
}
/**
* Renders the procedure's doc comment as a blockquote.
*/
function renderProcDescription(proc: Procedure): string[] {
const description = extractProcedureComments(proc);
if (!description) {
return [];
}
const lines: string[] = [];
for (const descLine of description.split('\n')) {
lines.push(`> ${descLine}`);
}
lines.push('');
return lines;
}
/**
* Renders the procedure's return type with linked type references.
*/
function renderReturnsSection(proc: Procedure): string[] {
return [
...sectionHeading('Returns'),
'',
resolveTypeLink(proc.returnType, true),
'',
];
}