From dd35524c6e686101361ce7e188b9df68e1d9e6ec Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 13 Jul 2023 18:22:05 -0400 Subject: [PATCH 1/4] Improve JS Ref docs --- common/config/rush/pnpm-lock.yaml | 42 ++++++++------------------ packages/compiler/src/core/types.ts | 4 +++ packages/compiler/src/core/util.ts | 1 + packages/ref-doc/package.json | 4 ++- packages/ref-doc/src/api-docs.ts | 46 +++++++++++++++++++++++++---- 5 files changed, 60 insertions(+), 37 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 8d3affaa4c8..ce6f006774e 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1113,10 +1113,16 @@ importers: '@typespec/compiler': specifier: workspace:~0.46.0 version: link:../compiler + js-yaml: + specifier: ~4.1.0 + version: 4.1.0 prettier: specifier: ~2.8.7 version: 2.8.7 devDependencies: + '@types/js-yaml': + specifier: ~4.0.1 + version: 4.0.1 '@types/mocha': specifier: ~10.0.1 version: 10.0.1 @@ -1151,8 +1157,8 @@ importers: specifier: ~0.24.8 version: 0.24.8(typescript@5.1.3) typedoc-plugin-markdown: - specifier: ~3.15.1 - version: 3.15.1(typedoc@0.24.8) + specifier: ~4.0.0-next.17 + version: 4.0.0-next.17(prettier@2.8.7)(typedoc@0.24.8) typescript: specifier: ~5.1.3 version: 5.1.3 @@ -10241,19 +10247,6 @@ packages: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} dev: false - /handlebars@4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: true - /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -14653,12 +14646,13 @@ packages: is-typedarray: 1.0.0 dev: false - /typedoc-plugin-markdown@3.15.1(typedoc@0.24.8): - resolution: {integrity: sha512-TaXE8gc8s5YepU1Ogyqfkh+khPE1/n4rV5vaoZCNyXvSLv62jWmHf443lHiQh7r07qAimUOKAndaaufAeIUSiQ==} + /typedoc-plugin-markdown@4.0.0-next.17(prettier@2.8.7)(typedoc@0.24.8): + resolution: {integrity: sha512-hzIoOt81PTkO50m+QJAo4B4tnsmp5sfv7kQfPOx/ZKRLODoa3buQzo2k6/sHGahUeKIyzHtqoiEFzB6Bl4nHQQ==} peerDependencies: + prettier: '>=1.8.0' typedoc: '>=0.24.0' dependencies: - handlebars: 4.7.7 + prettier: 2.8.7 typedoc: 0.24.8(typescript@5.1.3) dev: true @@ -14699,14 +14693,6 @@ packages: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: true - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - /underscore@1.13.6: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true @@ -15461,10 +15447,6 @@ packages: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - /wordwrapjs@4.0.1: resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} engines: {node: '>=8.0.0'} diff --git a/packages/compiler/src/core/types.ts b/packages/compiler/src/core/types.ts index fc4e76273b0..255c2ca2af5 100644 --- a/packages/compiler/src/core/types.ts +++ b/packages/compiler/src/core/types.ts @@ -620,6 +620,9 @@ export interface SymbolLinks { instantiations?: TypeInstantiationMap; } +/** + * @hidden bug in typedoc + */ export interface SymbolTable extends ReadonlyMap { /** * Duplicate @@ -678,6 +681,7 @@ export interface TypeInstantiationMap { /** * A map where keys can be changed without changing enumeration order. + * @hidden bug in typedoc */ export interface RekeyableMap extends Map { /** diff --git a/packages/compiler/src/core/util.ts b/packages/compiler/src/core/util.ts index b8d934ff78d..40f84d721e4 100644 --- a/packages/compiler/src/core/util.ts +++ b/packages/compiler/src/core/util.ts @@ -342,6 +342,7 @@ export class MultiKeyMap { * A map with exactly two keys per value. * * Functionally the same as `MultiKeyMap<[K1, K2], V>`, but more efficient. + * @hidden bug in typedoc */ export class TwoLevelMap extends Map> { /** diff --git a/packages/ref-doc/package.json b/packages/ref-doc/package.json index 11234abd24f..a19e72a95cb 100644 --- a/packages/ref-doc/package.json +++ b/packages/ref-doc/package.json @@ -52,6 +52,7 @@ ], "dependencies": { "@typespec/compiler": "workspace:~0.46.0", + "js-yaml": "~4.1.0", "prettier": "~2.8.7" }, "devDependencies": { @@ -60,13 +61,14 @@ "@types/mocha": "~10.0.1", "@types/node": "~18.11.9", "@types/prettier": "2.6.0", + "@types/js-yaml": "~4.0.1", "c8": "~8.0.0", "eslint": "^8.42.0", "mocha-junit-reporter": "~2.2.0", "mocha-multi-reporters": "~1.5.1", "mocha": "~10.2.0", "rimraf": "~5.0.1", - "typedoc-plugin-markdown": "~3.15.1", + "typedoc-plugin-markdown": "~4.0.0-next.17", "typedoc": "~0.24.8", "typescript": "~5.1.3" } diff --git a/packages/ref-doc/src/api-docs.ts b/packages/ref-doc/src/api-docs.ts index 1ae2468e2e9..496f04e2947 100644 --- a/packages/ref-doc/src/api-docs.ts +++ b/packages/ref-doc/src/api-docs.ts @@ -1,15 +1,27 @@ import { joinPaths } from "@typespec/compiler"; import { writeFile } from "fs/promises"; -import { Application } from "typedoc"; -import { load } from "typedoc-plugin-markdown"; +import { dump } from "js-yaml"; +import { Application, DeclarationReflection, PageEvent, ReflectionKind } from "typedoc"; +import { PluginOptions, load } from "typedoc-plugin-markdown"; export async function generateJsApiDocs(libraryPath: string, outputDir: string) { const app = new Application(); + loadRenderer(app); load(app); - const markdownPluginOptions: any = { - entryDocument: "index.md", - readme: "none", + const markdownPluginOptions: Partial = { + entryFileName: "index.md", + propertiesFormat: "table", + enumMembersFormat: "table", + typeDeclarationFormat: "table", + hidePageTitle: true, + hideBreadcrumbs: true, + hideKindPrefix: true, + hideInPageTOC: true, + hidePageHeader: true, + tocFormat: "list", + flattenOutputFiles: true, + identifiersAsCodeBlocks: true, }; app.bootstrap({ @@ -17,7 +29,8 @@ export async function generateJsApiDocs(libraryPath: string, outputDir: string) entryPoints: [libraryPath], entryPointStrategy: "legacy-packages", githubPages: false, - readme: false, + readme: "none", + hideGenerator: true, disableSources: true, ...markdownPluginOptions, }); @@ -41,3 +54,24 @@ export async function generateJsApiDocs(libraryPath: string, outputDir: string) }) ); } + +export function loadRenderer(app: Application) { + app.renderer.on(PageEvent.END, (page: PageEvent) => { + if (page.contents) { + const frontMatter = createFrontMatter(page.model); + page.contents = frontMatter + page.contents.replace(/\\ Date: Thu, 13 Jul 2023 21:29:45 -0400 Subject: [PATCH 2/4] Fix --- .../emitter-metadata-handling.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/extending-typespec/emitter-metadata-handling.md b/docs/extending-typespec/emitter-metadata-handling.md index 3adac11f7b3..89383ee24e9 100644 --- a/docs/extending-typespec/emitter-metadata-handling.md +++ b/docs/extending-typespec/emitter-metadata-handling.md @@ -23,16 +23,16 @@ However, if your emitter does want to split types as OpenAPI does, then it will These are the main API involved in handling these features. See the linked API reference documentation for more details. -- [`getRequestVisibility(HttpVerb): Visibility`](../standard-library/http/reference/js-api/index.md#getrequestvisibility) - Use this to determine the visibility implied for data in the request parameters or body. Also note that [`Visibility.Read`](../standard-library/http/reference/js-api/enums/Visibility#item) is always applied for response data and therefore there is no corresponding API for the response. +- [`getRequestVisibility(HttpVerb): Visibility`](../standard-library/http/reference/js-api/index.md#getrequestvisibility) - Use this to determine the visibility implied for data in the request parameters or body. Also note that [`Visibility.Read`](../standard-library/http/reference/js-api/Enumeration.Visibility.md#item) is always applied for response data and therefore there is no corresponding API for the response. -- [`MetadataInfo`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md) - Create this once for each program using [`createMetadataInfo(Program, MetadataInfoOptions)`](../standard-library/http/reference/js-api/index.md#createmetadatainfo) then use it to reason about metadata and visibility implications with the API below. +- [`MetadataInfo`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md) - Create this once for each program using [`createMetadataInfo(Program, MetadataInfoOptions)`](../standard-library/http/reference/js-api/index.md#createmetadatainfo) then use it to reason about metadata and visibility implications with the API below. -- [`MetadataInfo.getEffectivePayloadType(Type, Visibility): Type`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#geteffectivepayloadtype) - Use this recursively on every type that is referenced. When given an anonymous model sourced entirely from a single named model after metadata is moved elsewhere or invisible properties are removed, it will recover the named model. This handles the commonly discussed case of seeing that `op something(...Thing)` receives a `Thing` in its request body, but also many other cases. +- [`MetadataInfo.getEffectivePayloadType(Type, Visibility): Type`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#geteffectivepayloadtype) - Use this recursively on every type that is referenced. When given an anonymous model sourced entirely from a single named model after metadata is moved elsewhere or invisible properties are removed, it will recover the named model. This handles the commonly discussed case of seeing that `op something(...Thing)` receives a `Thing` in its request body, but also many other cases.. -- [`MetadataInfo.isTransformed(Model, Visibility)`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#istransformed) - Use this to check if a type undergoes any changes in shape due to visibility or metadata. If not, this can allow for simplifications in emit. +- [`MetadataInfo.isTransformed(Model, Visibility)`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#istransformed) - Use this to check if a type undergoes any changes in shape due to visibility or metadata. If not, this can allow for simplifications in emit. -- [`MetadataInfo.isPayloadProperty(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#ispayloadproperty) - Use this to check if a property is transmitted as an object property in the payload and is not invisible or metadata sent elsewhere. +- [`MetadataInfo.isPayloadProperty(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#ispayloadproperty) - Use this to check if a property is transmitted as an object property in the payload and is not invisible or metadata sent elsewhere. -- [`MetadataInfo.isOptional(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#isoptional) - Use this to determine if a property is optional for the given visibility. This will differ from `ModelProperty.isOptional` when the Visibility is Update in which case the property is always considered optional. +- [`MetadataInfo.isOptional(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#isoptional) - Use this to determine if a property is optional for the given visibility. This will differ from `ModelProperty.isOptional` when the Visibility is Update in which case the property is always considered optional. -- [`Visibility.Item`](../standard-library/http/reference/js-api/enums/Visibility#item) - Add this flag when recursing into an array. This moves all metadata into the payload, which can be useful in scenarios like batching API calls. +- [`Visibility.Item`](../standard-library/http/reference/js-api/Enumeration.Visibility#item) - Add this flag when recursing into an array. This moves all metadata into the payload, which can be useful in scenarios like batching API calls. From 67c86b69eba1b868db96d3b0d59e2a1686aa924e Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 13 Jul 2023 21:44:54 -0400 Subject: [PATCH 3/4] changelog --- .../docs-better-js-docs_2023-07-14-01-44.json | 10 ++++++++++ packages/ref-doc/src/api-docs.ts | 12 ++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 common/changes/@typespec/compiler/docs-better-js-docs_2023-07-14-01-44.json diff --git a/common/changes/@typespec/compiler/docs-better-js-docs_2023-07-14-01-44.json b/common/changes/@typespec/compiler/docs-better-js-docs_2023-07-14-01-44.json new file mode 100644 index 00000000000..5945164bd23 --- /dev/null +++ b/common/changes/@typespec/compiler/docs-better-js-docs_2023-07-14-01-44.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@typespec/compiler", + "comment": "", + "type": "none" + } + ], + "packageName": "@typespec/compiler" +} \ No newline at end of file diff --git a/packages/ref-doc/src/api-docs.ts b/packages/ref-doc/src/api-docs.ts index 496f04e2947..b94dab39b11 100644 --- a/packages/ref-doc/src/api-docs.ts +++ b/packages/ref-doc/src/api-docs.ts @@ -14,11 +14,11 @@ export async function generateJsApiDocs(libraryPath: string, outputDir: string) propertiesFormat: "table", enumMembersFormat: "table", typeDeclarationFormat: "table", - hidePageTitle: true, - hideBreadcrumbs: true, - hideKindPrefix: true, - hideInPageTOC: true, - hidePageHeader: true, + // hidePageTitle: true, + // hideBreadcrumbs: true, + // hideKindPrefix: true, + // hideInPageTOC: true, + // hidePageHeader: true, tocFormat: "list", flattenOutputFiles: true, identifiersAsCodeBlocks: true, @@ -31,7 +31,7 @@ export async function generateJsApiDocs(libraryPath: string, outputDir: string) githubPages: false, readme: "none", hideGenerator: true, - disableSources: true, + disableSources: false, ...markdownPluginOptions, }); const project = app.convert(); From bd95a69164ecb3c052c57685e13c79c970cc9509 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 13 Jul 2023 21:50:32 -0400 Subject: [PATCH 4/4] Fix --- packages/ref-doc/src/api-docs.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/ref-doc/src/api-docs.ts b/packages/ref-doc/src/api-docs.ts index b94dab39b11..ed4a9db7bc4 100644 --- a/packages/ref-doc/src/api-docs.ts +++ b/packages/ref-doc/src/api-docs.ts @@ -14,11 +14,12 @@ export async function generateJsApiDocs(libraryPath: string, outputDir: string) propertiesFormat: "table", enumMembersFormat: "table", typeDeclarationFormat: "table", - // hidePageTitle: true, - // hideBreadcrumbs: true, - // hideKindPrefix: true, - // hideInPageTOC: true, - // hidePageHeader: true, + hidePageTitle: true, + hideBreadcrumbs: true, + hideKindPrefix: true, + hideInPageTOC: true, + hidePageHeader: true, + tocFormat: "list", flattenOutputFiles: true, identifiersAsCodeBlocks: true,