@typespec/tspd 0.70.0-dev.1 → 0.70.0-dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/src/cli.js +85 -103
  2. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts +8 -0
  3. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts.map +1 -0
  4. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.js +16 -0
  5. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx +12 -0
  6. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx.map +1 -0
  7. package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts +16 -0
  8. package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts.map +1 -0
  9. package/dist/src/gen-extern-signatures/components/decorator-signature-type.js +404 -0
  10. package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx +316 -0
  11. package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx.map +1 -0
  12. package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts +12 -0
  13. package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts.map +1 -0
  14. package/dist/src/gen-extern-signatures/components/decorators-signatures.js +107 -0
  15. package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx +60 -0
  16. package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx.map +1 -0
  17. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts +10 -0
  18. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts.map +1 -0
  19. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.js +39 -0
  20. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx +18 -0
  21. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx.map +1 -0
  22. package/dist/src/gen-extern-signatures/components/tspd-context.d.ts +10 -0
  23. package/dist/src/gen-extern-signatures/components/tspd-context.d.ts.map +1 -0
  24. package/dist/src/gen-extern-signatures/components/tspd-context.js +22 -0
  25. package/dist/src/gen-extern-signatures/components/tspd-context.js.map +1 -0
  26. package/dist/src/gen-extern-signatures/doc-builder.js +10 -12
  27. package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts +17 -0
  28. package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts.map +1 -0
  29. package/dist/src/gen-extern-signatures/external-packages/compiler.js +10 -0
  30. package/dist/src/gen-extern-signatures/external-packages/compiler.js.map +1 -0
  31. package/dist/src/gen-extern-signatures/gen-extern-signatures.d.ts.map +1 -1
  32. package/dist/src/gen-extern-signatures/gen-extern-signatures.js +109 -102
  33. package/dist/src/gen-extern-signatures/gen-extern-signatures.js.map +1 -1
  34. package/dist/src/gen-extern-signatures/types.js +1 -2
  35. package/dist/src/ref-doc/api-docs.js +56 -56
  36. package/dist/src/ref-doc/emitters/docusaurus.js +156 -209
  37. package/dist/src/ref-doc/emitters/markdown.js +278 -327
  38. package/dist/src/ref-doc/emitters/starlight.js +154 -190
  39. package/dist/src/ref-doc/experimental.js +48 -45
  40. package/dist/src/ref-doc/extractor.js +486 -449
  41. package/dist/src/ref-doc/index.js +1 -2
  42. package/dist/src/ref-doc/lib.js +29 -26
  43. package/dist/src/ref-doc/types.js +1 -2
  44. package/dist/src/ref-doc/utils/markdown.js +37 -44
  45. package/dist/src/ref-doc/utils/type-signature.js +89 -98
  46. package/package.json +10 -6
  47. package/dist/src/gen-extern-signatures/decorators-signatures.d.ts +0 -5
  48. package/dist/src/gen-extern-signatures/decorators-signatures.d.ts.map +0 -1
  49. package/dist/src/gen-extern-signatures/decorators-signatures.js +0 -338
  50. package/dist/src/gen-extern-signatures/decorators-signatures.js.map +0 -1
@@ -1,339 +1,290 @@
1
- import { getEntityName, isType, resolvePath, } from "@typespec/compiler";
1
+ import { getEntityName, isType, resolvePath } from "@typespec/compiler";
2
2
  import { readFile } from "fs/promises";
3
3
  import { stringify } from "yaml";
4
- import { codeblock, inlinecode, link, renderMarkdowDoc, section, table, } from "../utils/markdown.js";
4
+ import { codeblock, inlinecode, link, renderMarkdowDoc, section, table } from "../utils/markdown.js";
5
5
  async function loadTemplate(projectRoot, name) {
6
- try {
7
- const content = await readFile(resolvePath(projectRoot, `.tspd/docs/${name}.md`));
8
- return content.toString();
9
- }
10
- catch (e) {
11
- if (typeof e === "object" && e?.code === "ENOENT") {
12
- return undefined;
13
- }
14
- throw e;
15
- }
6
+ try {
7
+ const content = await readFile(resolvePath(projectRoot, `.tspd/docs/${name}.md`));
8
+ return content.toString();
9
+ } catch (e) {
10
+ if (typeof e === "object" && e?.code === "ENOENT") {
11
+ return undefined;
12
+ }
13
+ throw e;
14
+ }
16
15
  }
17
16
  export async function renderReadme(refDoc, projectRoot) {
18
- const content = [];
19
- const renderer = new MarkdownRenderer(refDoc);
20
- const headerTemplate = await loadTemplate(projectRoot, "header");
21
- if (headerTemplate) {
22
- content.push(headerTemplate);
23
- }
24
- if (refDoc.description) {
25
- content.push(refDoc.description);
26
- }
27
- content.push(renderer.install(refDoc));
28
- const usageTemplate = await loadTemplate(projectRoot, "usage");
29
- if (usageTemplate) {
30
- content.push(section("Usage", [usageTemplate]));
31
- }
32
- if (refDoc.emitter?.options) {
33
- content.push(renderer.emitterUsage(refDoc));
34
- }
35
- if (refDoc.linter) {
36
- content.push(renderer.linterUsage(refDoc));
37
- }
38
- if (refDoc.namespaces.some((x) => x.decorators.length > 0)) {
39
- content.push(section("Decorators", renderer.decoratorsSection(refDoc, { includeToc: true })));
40
- }
41
- const footerTemplate = await loadTemplate(projectRoot, "footer");
42
- if (footerTemplate) {
43
- content.push(footerTemplate);
44
- }
45
- return renderMarkdowDoc(section(refDoc.name, content));
17
+ const content = [];
18
+ const renderer = new MarkdownRenderer(refDoc);
19
+ const headerTemplate = await loadTemplate(projectRoot, "header");
20
+ if (headerTemplate) {
21
+ content.push(headerTemplate);
22
+ }
23
+ if (refDoc.description) {
24
+ content.push(refDoc.description);
25
+ }
26
+ content.push(renderer.install(refDoc));
27
+ const usageTemplate = await loadTemplate(projectRoot, "usage");
28
+ if (usageTemplate) {
29
+ content.push(section("Usage", [usageTemplate]));
30
+ }
31
+ if (refDoc.emitter?.options) {
32
+ content.push(renderer.emitterUsage(refDoc));
33
+ }
34
+ if (refDoc.linter) {
35
+ content.push(renderer.linterUsage(refDoc));
36
+ }
37
+ if (refDoc.namespaces.some(x => x.decorators.length > 0)) {
38
+ content.push(section("Decorators", renderer.decoratorsSection(refDoc, {
39
+ includeToc: true
40
+ })));
41
+ }
42
+ const footerTemplate = await loadTemplate(projectRoot, "footer");
43
+ if (footerTemplate) {
44
+ content.push(footerTemplate);
45
+ }
46
+ return renderMarkdowDoc(section(refDoc.name, content));
46
47
  }
47
48
  export function groupByNamespace(namespaces, callback) {
48
- const content = [];
49
- for (const namespace of namespaces) {
50
- const contentForNamespace = callback(namespace);
51
- if (contentForNamespace) {
52
- content.push(section(namespace.id, contentForNamespace));
53
- }
54
- }
55
- return content;
49
+ const content = [];
50
+ for (const namespace of namespaces) {
51
+ const contentForNamespace = callback(namespace);
52
+ if (contentForNamespace) {
53
+ content.push(section(namespace.id, contentForNamespace));
54
+ }
55
+ }
56
+ return content;
56
57
  }
58
+
57
59
  /**
58
60
  * Github flavored markdown renderer.
59
61
  */
60
62
  export class MarkdownRenderer {
61
- refDoc;
62
- constructor(refDoc) {
63
- this.refDoc = refDoc;
64
- }
65
- headingTitle(item) {
66
- return inlinecode(item.name);
67
- }
68
- anchorId(item) {
69
- return `${item.name.toLowerCase().replace(/ /g, "-")}`;
70
- }
71
- deprecationNotice(notice) {
72
- return `_Deprecated: ${notice.message}_`;
73
- }
74
- typeSection(type, content) {
75
- const deprecated = type.deprecated ? this.deprecationNotice(type.deprecated) : [];
76
- return section(this.headingTitle(type), [deprecated, content]);
77
- }
78
- //#region TypeSpec types
79
- operation(op) {
80
- const content = ["", op.doc, codeblock(op.signature, "typespec"), ""];
81
- if (op.templateParameters) {
82
- content.push(this.templateParameters(op.templateParameters));
83
- }
84
- content.push(this.examples(op.examples));
85
- return this.typeSection(op, content);
86
- }
87
- interface(iface) {
88
- const content = ["", iface.doc, codeblock(iface.signature, "typespec"), ""];
89
- if (iface.templateParameters) {
90
- content.push(this.templateParameters(iface.templateParameters));
91
- }
92
- if (iface.interfaceOperations.length > 0) {
93
- for (const op of iface.interfaceOperations) {
94
- content.push(this.operation(op));
95
- }
96
- }
97
- content.push(this.examples(iface.examples));
98
- return this.typeSection(iface, content);
99
- }
100
- model(model) {
101
- const content = ["", model.doc, codeblock(model.signature, "typespec"), ""];
102
- if (model.templateParameters) {
103
- content.push(this.templateParameters(model.templateParameters));
104
- }
105
- content.push(this.examples(model.examples));
106
- content.push(this.modelProperties(model));
107
- return this.typeSection(model, content);
108
- }
109
- modelProperties(model) {
110
- const content = [];
111
- if (model.properties.size === 0 && model.type.indexer === undefined) {
112
- return section("Properties", "None");
113
- }
114
- const rows = [
115
- { name: "Name", type: "Type", doc: "Description" },
116
- ];
117
- for (const prop of model.properties.values()) {
118
- const propRows = this.modelPropertyRows(prop);
119
- for (const row of propRows) {
120
- rows.push(row);
121
- }
122
- }
123
- if (model.type.indexer) {
124
- rows.push({
125
- name: "",
126
- type: this.ref(model.type.indexer.value),
127
- doc: "Additional properties",
128
- });
129
- }
130
- content.push(table(rows.map((x) => [x.name, x.type, x.doc])));
131
- return section("Properties", content);
132
- }
133
- modelPropertyRows(prop) {
134
- const name = `${prop.name}${prop.type.optional ? "?" : ""}`;
135
- const base = {
136
- name: prop.deprecated ? `~~${name}~~ _DEPRECATED_` : name,
137
- type: this.ref(prop.type.type),
138
- doc: prop.doc,
139
- };
140
- if (prop.type.type.kind === "Model" && prop.type.type.name === "") {
141
- return [
142
- base,
143
- ...[...prop.type.type.properties.values()].map((x) => ({
144
- name: `${prop.name}.${x.name}${x.optional ? "?" : ""}`,
145
- type: this.ref(x.type),
146
- doc: "",
147
- })),
148
- ];
149
- }
150
- return [base];
151
- }
152
- ref(type, prefix = "") {
153
- const namedType = isType(type) && this.refDoc.getNamedTypeRefDoc(type);
154
- if (namedType) {
155
- return link(prefix + inlinecode(namedType.name), `${this.filename(namedType)}#${this.anchorId(namedType)}`);
156
- }
157
- // So we don't show (anonymous model) until this gets improved.
158
- if ("kind" in type && type.kind === "Model" && type.name === "" && type.properties.size > 0) {
159
- return inlinecode(prefix + "{...}");
160
- }
161
- return inlinecode(prefix +
162
- getEntityName(type, {
163
- namespaceFilter: (ns) => !this.refDoc.namespaces.some((x) => x.name === ns.name),
164
- }));
165
- }
166
- enum(e) {
167
- const content = [
168
- "",
169
- e.doc,
170
- codeblock(e.signature, "typespec"),
171
- "",
172
- this.enumMembers(e),
173
- this.examples(e.examples),
174
- ];
175
- return this.typeSection(e, content);
176
- }
177
- enumMembers(e) {
178
- const rows = [...e.members.values()].map((x) => {
179
- return [
180
- x.name,
181
- x.type.value
182
- ? inlinecode(typeof x.type.value === "string" ? `"${x.type.value}"` : x.type.value.toString())
183
- : "",
184
- x.doc,
185
- ];
186
- });
187
- return table([["Name", "Value", "Description"], ...rows]);
188
- }
189
- union(union) {
190
- const content = ["", union.doc, codeblock(union.signature, "typespec"), ""];
191
- if (union.templateParameters) {
192
- content.push(this.templateParameters(union.templateParameters));
193
- }
194
- content.push(this.examples(union.examples));
195
- return this.typeSection(union, content);
196
- }
197
- scalar(scalar) {
198
- const content = ["", scalar.doc, codeblock(scalar.signature, "typespec"), ""];
199
- if (scalar.templateParameters) {
200
- content.push(this.templateParameters(scalar.templateParameters));
201
- }
202
- content.push(this.examples(scalar.examples));
203
- return this.typeSection(scalar, content);
204
- }
205
- templateParameters(templateParameters) {
206
- const paramTable = [["Name", "Description"]];
207
- for (const param of templateParameters) {
208
- paramTable.push([param.name, param.doc]);
209
- }
210
- return section("Template Parameters", [table(paramTable), ""]);
211
- }
212
- decorator(dec) {
213
- const content = ["", dec.doc, codeblock(dec.signature, "typespec"), ""];
214
- content.push(section("Target", [dec.target.doc, this.ref(dec.target.type.type), ""]));
215
- if (dec.parameters.length > 0) {
216
- const paramTable = [["Name", "Type", "Description"]];
217
- for (const param of dec.parameters) {
218
- paramTable.push([param.name, this.MixedParameterConstraint(param.type.type), param.doc]);
219
- }
220
- content.push(section("Parameters", [table(paramTable), ""]));
221
- }
222
- else {
223
- content.push(section("Parameters", ["None", ""]));
224
- }
225
- content.push(this.examples(dec.examples));
226
- return this.typeSection(dec, content);
227
- }
228
- MixedParameterConstraint(constraint) {
229
- return [
230
- ...(constraint.type ? [this.ref(constraint.type)] : []),
231
- ...(constraint.valueType ? [this.ref(constraint.valueType, "valueof ")] : []),
232
- ].join(" | ");
233
- }
234
- examples(examples) {
235
- const content = [];
236
- if (examples.length === 0) {
237
- return "";
238
- }
239
- for (const example of examples) {
240
- const exampleContent = ["", example.content, ""];
241
- if (example.title) {
242
- content.push(section(example.title, exampleContent));
243
- }
244
- else {
245
- content.push(exampleContent);
246
- }
247
- }
248
- return section("Examples", content);
249
- }
250
- // #endregion TypeSpec types
251
- /** Render all decorators */
252
- decoratorsSection(refDoc, options = {}) {
253
- return groupByNamespace(refDoc.namespaces, (namespace) => {
254
- if (namespace.decorators.length === 0) {
255
- return undefined;
256
- }
257
- return [
258
- options.includeToc ? this.toc(namespace.decorators) : [],
259
- namespace.decorators.map((x) => [this.decorator(x), ""]),
260
- ];
261
- });
262
- }
263
- toc(items) {
264
- return items.map((item) => ` - [${inlinecode(item.name)}](${this.filename(item)}#${this.anchorId(item)})`);
265
- }
266
- filename(type) {
267
- return "";
268
- }
269
- install(refDoc) {
270
- return section("Install", [codeblock(`npm install ${refDoc.name}`, "bash")]);
271
- }
272
- emitterUsage(refDoc) {
273
- if (refDoc.emitter?.options === undefined) {
274
- return [];
275
- }
276
- return [
277
- section("Usage", [
278
- "1. Via the command line",
279
- codeblock(`tsp compile . --emit=${refDoc.name}`, "bash"),
280
- "2. Via the config",
281
- codeblock(`emit:\n - "${refDoc.name}" `, "yaml"),
282
- "The config can be extended with options as follows:",
283
- codeblock(`emit:\n - "${refDoc.name}"\noptions:\n "${refDoc.name}":\n option: value`, "yaml"),
284
- ]),
285
- this.emitterOptions(refDoc.emitter.options),
286
- ];
287
- }
288
- emitterOptions(options) {
289
- const content = [];
290
- content.push(section(`${inlinecode("emitter-output-dir")}`, [
291
- `**Type:** ${inlinecode("absolutePath")}`,
292
- "",
293
- `Defines the emitter output directory. Defaults to \`{output-dir}/${this.refDoc.name}\``,
294
- `See [Configuring output directory for more info](https://typespec.io/docs/handbook/configuration/configuration/#configuring-output-directory)`,
295
- ]));
296
- for (const option of options) {
297
- content.push(section(`${inlinecode(option.name)}`, [
298
- `**Type:** ${inlinecode(option.type)}`,
299
- "",
300
- option.doc,
301
- ]));
302
- }
303
- return section("Emitter options", content);
304
- }
305
- linterUsage(refDoc) {
306
- if (refDoc.linter === undefined) {
307
- return [];
308
- }
309
- const setupExample = stringify({
310
- linter: refDoc.linter.ruleSets
311
- ? { extends: [refDoc.linter.ruleSets[0].name] }
312
- : { rules: {} },
313
- });
314
- return [
315
- section("Usage", ["Add the following in `tspconfig.yaml`:", codeblock(setupExample, "yaml")]),
316
- refDoc.linter.ruleSets
317
- ? section("RuleSets", [
318
- "Available ruleSets:",
319
- refDoc.linter.ruleSets.map((item) => ` - ${inlinecode(item.name)}`),
320
- ])
321
- : [],
322
- section("Rules", this.linterRuleToc(refDoc.linter.rules)),
323
- ];
324
- }
325
- linterRuleToc(rules) {
326
- return table([
327
- ["Name", "Description"],
328
- ...rules.map((rule) => {
329
- const name = inlinecode(rule.name);
330
- const nameCell = rule.rule.url ? link(name, this.linterRuleLink(rule.rule.url)) : name;
331
- return [nameCell, rule.rule.description];
332
- }),
333
- ]);
334
- }
335
- linterRuleLink(url) {
336
- return url;
337
- }
338
- }
339
- //# sourceMappingURL=markdown.js.map
63
+ constructor(refDoc) {
64
+ this.refDoc = refDoc;
65
+ }
66
+ headingTitle(item) {
67
+ return inlinecode(item.name);
68
+ }
69
+ anchorId(item) {
70
+ return `${item.name.toLowerCase().replace(/ /g, "-")}`;
71
+ }
72
+ deprecationNotice(notice) {
73
+ return `_Deprecated: ${notice.message}_`;
74
+ }
75
+ typeSection(type, content) {
76
+ const deprecated = type.deprecated ? this.deprecationNotice(type.deprecated) : [];
77
+ return section(this.headingTitle(type), [deprecated, content]);
78
+ }
79
+
80
+ //#region TypeSpec types
81
+ operation(op) {
82
+ const content = ["", op.doc, codeblock(op.signature, "typespec"), ""];
83
+ if (op.templateParameters) {
84
+ content.push(this.templateParameters(op.templateParameters));
85
+ }
86
+ content.push(this.examples(op.examples));
87
+ return this.typeSection(op, content);
88
+ }
89
+ interface(iface) {
90
+ const content = ["", iface.doc, codeblock(iface.signature, "typespec"), ""];
91
+ if (iface.templateParameters) {
92
+ content.push(this.templateParameters(iface.templateParameters));
93
+ }
94
+ if (iface.interfaceOperations.length > 0) {
95
+ for (const op of iface.interfaceOperations) {
96
+ content.push(this.operation(op));
97
+ }
98
+ }
99
+ content.push(this.examples(iface.examples));
100
+ return this.typeSection(iface, content);
101
+ }
102
+ model(model) {
103
+ const content = ["", model.doc, codeblock(model.signature, "typespec"), ""];
104
+ if (model.templateParameters) {
105
+ content.push(this.templateParameters(model.templateParameters));
106
+ }
107
+ content.push(this.examples(model.examples));
108
+ content.push(this.modelProperties(model));
109
+ return this.typeSection(model, content);
110
+ }
111
+ modelProperties(model) {
112
+ const content = [];
113
+ if (model.properties.size === 0 && model.type.indexer === undefined) {
114
+ return section("Properties", "None");
115
+ }
116
+ const rows = [{
117
+ name: "Name",
118
+ type: "Type",
119
+ doc: "Description"
120
+ }];
121
+ for (const prop of model.properties.values()) {
122
+ const propRows = this.modelPropertyRows(prop);
123
+ for (const row of propRows) {
124
+ rows.push(row);
125
+ }
126
+ }
127
+ if (model.type.indexer) {
128
+ rows.push({
129
+ name: "",
130
+ type: this.ref(model.type.indexer.value),
131
+ doc: "Additional properties"
132
+ });
133
+ }
134
+ content.push(table(rows.map(x => [x.name, x.type, x.doc])));
135
+ return section("Properties", content);
136
+ }
137
+ modelPropertyRows(prop) {
138
+ const name = `${prop.name}${prop.type.optional ? "?" : ""}`;
139
+ const base = {
140
+ name: prop.deprecated ? `~~${name}~~ _DEPRECATED_` : name,
141
+ type: this.ref(prop.type.type),
142
+ doc: prop.doc
143
+ };
144
+ if (prop.type.type.kind === "Model" && prop.type.type.name === "") {
145
+ return [base, ...[...prop.type.type.properties.values()].map(x => ({
146
+ name: `${prop.name}.${x.name}${x.optional ? "?" : ""}`,
147
+ type: this.ref(x.type),
148
+ doc: ""
149
+ }))];
150
+ }
151
+ return [base];
152
+ }
153
+ ref(type, prefix = "") {
154
+ const namedType = isType(type) && this.refDoc.getNamedTypeRefDoc(type);
155
+ if (namedType) {
156
+ return link(prefix + inlinecode(namedType.name), `${this.filename(namedType)}#${this.anchorId(namedType)}`);
157
+ }
158
+
159
+ // So we don't show (anonymous model) until this gets improved.
160
+ if ("kind" in type && type.kind === "Model" && type.name === "" && type.properties.size > 0) {
161
+ return inlinecode(prefix + "{...}");
162
+ }
163
+ return inlinecode(prefix + getEntityName(type, {
164
+ namespaceFilter: ns => !this.refDoc.namespaces.some(x => x.name === ns.name)
165
+ }));
166
+ }
167
+ enum(e) {
168
+ const content = ["", e.doc, codeblock(e.signature, "typespec"), "", this.enumMembers(e), this.examples(e.examples)];
169
+ return this.typeSection(e, content);
170
+ }
171
+ enumMembers(e) {
172
+ const rows = [...e.members.values()].map(x => {
173
+ return [x.name, x.type.value ? inlinecode(typeof x.type.value === "string" ? `"${x.type.value}"` : x.type.value.toString()) : "", x.doc];
174
+ });
175
+ return table([["Name", "Value", "Description"], ...rows]);
176
+ }
177
+ union(union) {
178
+ const content = ["", union.doc, codeblock(union.signature, "typespec"), ""];
179
+ if (union.templateParameters) {
180
+ content.push(this.templateParameters(union.templateParameters));
181
+ }
182
+ content.push(this.examples(union.examples));
183
+ return this.typeSection(union, content);
184
+ }
185
+ scalar(scalar) {
186
+ const content = ["", scalar.doc, codeblock(scalar.signature, "typespec"), ""];
187
+ if (scalar.templateParameters) {
188
+ content.push(this.templateParameters(scalar.templateParameters));
189
+ }
190
+ content.push(this.examples(scalar.examples));
191
+ return this.typeSection(scalar, content);
192
+ }
193
+ templateParameters(templateParameters) {
194
+ const paramTable = [["Name", "Description"]];
195
+ for (const param of templateParameters) {
196
+ paramTable.push([param.name, param.doc]);
197
+ }
198
+ return section("Template Parameters", [table(paramTable), ""]);
199
+ }
200
+ decorator(dec) {
201
+ const content = ["", dec.doc, codeblock(dec.signature, "typespec"), ""];
202
+ content.push(section("Target", [dec.target.doc, this.ref(dec.target.type.type), ""]));
203
+ if (dec.parameters.length > 0) {
204
+ const paramTable = [["Name", "Type", "Description"]];
205
+ for (const param of dec.parameters) {
206
+ paramTable.push([param.name, this.MixedParameterConstraint(param.type.type), param.doc]);
207
+ }
208
+ content.push(section("Parameters", [table(paramTable), ""]));
209
+ } else {
210
+ content.push(section("Parameters", ["None", ""]));
211
+ }
212
+ content.push(this.examples(dec.examples));
213
+ return this.typeSection(dec, content);
214
+ }
215
+ MixedParameterConstraint(constraint) {
216
+ return [...(constraint.type ? [this.ref(constraint.type)] : []), ...(constraint.valueType ? [this.ref(constraint.valueType, "valueof ")] : [])].join(" | ");
217
+ }
218
+ examples(examples) {
219
+ const content = [];
220
+ if (examples.length === 0) {
221
+ return "";
222
+ }
223
+ for (const example of examples) {
224
+ const exampleContent = ["", example.content, ""];
225
+ if (example.title) {
226
+ content.push(section(example.title, exampleContent));
227
+ } else {
228
+ content.push(exampleContent);
229
+ }
230
+ }
231
+ return section("Examples", content);
232
+ }
233
+ // #endregion TypeSpec types
234
+
235
+ /** Render all decorators */
236
+ decoratorsSection(refDoc, options = {}) {
237
+ return groupByNamespace(refDoc.namespaces, namespace => {
238
+ if (namespace.decorators.length === 0) {
239
+ return undefined;
240
+ }
241
+ return [options.includeToc ? this.toc(namespace.decorators) : [], namespace.decorators.map(x => [this.decorator(x), ""])];
242
+ });
243
+ }
244
+ toc(items) {
245
+ return items.map(item => ` - [${inlinecode(item.name)}](${this.filename(item)}#${this.anchorId(item)})`);
246
+ }
247
+ filename(type) {
248
+ return "";
249
+ }
250
+ install(refDoc) {
251
+ return section("Install", [codeblock(`npm install ${refDoc.name}`, "bash")]);
252
+ }
253
+ emitterUsage(refDoc) {
254
+ if (refDoc.emitter?.options === undefined) {
255
+ return [];
256
+ }
257
+ return [section("Usage", ["1. Via the command line", codeblock(`tsp compile . --emit=${refDoc.name}`, "bash"), "2. Via the config", codeblock(`emit:\n - "${refDoc.name}" `, "yaml"), "The config can be extended with options as follows:", codeblock(`emit:\n - "${refDoc.name}"\noptions:\n "${refDoc.name}":\n option: value`, "yaml")]), this.emitterOptions(refDoc.emitter.options)];
258
+ }
259
+ emitterOptions(options) {
260
+ const content = [];
261
+ content.push(section(`${inlinecode("emitter-output-dir")}`, [`**Type:** ${inlinecode("absolutePath")}`, "", `Defines the emitter output directory. Defaults to \`{output-dir}/${this.refDoc.name}\``, `See [Configuring output directory for more info](https://typespec.io/docs/handbook/configuration/configuration/#configuring-output-directory)`]));
262
+ for (const option of options) {
263
+ content.push(section(`${inlinecode(option.name)}`, [`**Type:** ${inlinecode(option.type)}`, "", option.doc]));
264
+ }
265
+ return section("Emitter options", content);
266
+ }
267
+ linterUsage(refDoc) {
268
+ if (refDoc.linter === undefined) {
269
+ return [];
270
+ }
271
+ const setupExample = stringify({
272
+ linter: refDoc.linter.ruleSets ? {
273
+ extends: [refDoc.linter.ruleSets[0].name]
274
+ } : {
275
+ rules: {}
276
+ }
277
+ });
278
+ return [section("Usage", ["Add the following in `tspconfig.yaml`:", codeblock(setupExample, "yaml")]), refDoc.linter.ruleSets ? section("RuleSets", ["Available ruleSets:", refDoc.linter.ruleSets.map(item => ` - ${inlinecode(item.name)}`)]) : [], section("Rules", this.linterRuleToc(refDoc.linter.rules))];
279
+ }
280
+ linterRuleToc(rules) {
281
+ return table([["Name", "Description"], ...rules.map(rule => {
282
+ const name = inlinecode(rule.name);
283
+ const nameCell = rule.rule.url ? link(name, this.linterRuleLink(rule.rule.url)) : name;
284
+ return [nameCell, rule.rule.description];
285
+ })]);
286
+ }
287
+ linterRuleLink(url) {
288
+ return url;
289
+ }
290
+ }