@microsoft/api-documenter 7.28.9 → 7.29.0
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.
- package/CHANGELOG.json +29 -0
- package/CHANGELOG.md +8 -1
- package/bin/api-documenter +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib-esm/cli/ApiDocumenterCommandLine.js +22 -0
- package/lib-esm/cli/ApiDocumenterCommandLine.js.map +1 -0
- package/lib-esm/cli/BaseAction.js +93 -0
- package/lib-esm/cli/BaseAction.js.map +1 -0
- package/lib-esm/cli/GenerateAction.js +45 -0
- package/lib-esm/cli/GenerateAction.js.map +1 -0
- package/lib-esm/cli/MarkdownAction.js +24 -0
- package/lib-esm/cli/MarkdownAction.js.map +1 -0
- package/lib-esm/cli/YamlAction.js +43 -0
- package/lib-esm/cli/YamlAction.js.map +1 -0
- package/lib-esm/documenters/DocumenterConfig.js +43 -0
- package/lib-esm/documenters/DocumenterConfig.js.map +1 -0
- package/lib-esm/documenters/ExperimentalYamlDocumenter.js +136 -0
- package/lib-esm/documenters/ExperimentalYamlDocumenter.js.map +1 -0
- package/lib-esm/documenters/IConfigFile.js +4 -0
- package/lib-esm/documenters/IConfigFile.js.map +1 -0
- package/lib-esm/documenters/MarkdownDocumenter.js +987 -0
- package/lib-esm/documenters/MarkdownDocumenter.js.map +1 -0
- package/lib-esm/documenters/OfficeYamlDocumenter.js +101 -0
- package/lib-esm/documenters/OfficeYamlDocumenter.js.map +1 -0
- package/lib-esm/documenters/YamlDocumenter.js +804 -0
- package/lib-esm/documenters/YamlDocumenter.js.map +1 -0
- package/lib-esm/index.js +6 -0
- package/lib-esm/index.js.map +1 -0
- package/lib-esm/markdown/CustomMarkdownEmitter.js +146 -0
- package/lib-esm/markdown/CustomMarkdownEmitter.js.map +1 -0
- package/lib-esm/markdown/MarkdownEmitter.js +190 -0
- package/lib-esm/markdown/MarkdownEmitter.js.map +1 -0
- package/lib-esm/nodes/CustomDocNodeKind.js +51 -0
- package/lib-esm/nodes/CustomDocNodeKind.js.map +1 -0
- package/lib-esm/nodes/DocEmphasisSpan.js +20 -0
- package/lib-esm/nodes/DocEmphasisSpan.js.map +1 -0
- package/lib-esm/nodes/DocHeading.js +26 -0
- package/lib-esm/nodes/DocHeading.js.map +1 -0
- package/lib-esm/nodes/DocNoteBox.js +22 -0
- package/lib-esm/nodes/DocNoteBox.js.map +1 -0
- package/lib-esm/nodes/DocTable.js +56 -0
- package/lib-esm/nodes/DocTable.js.map +1 -0
- package/lib-esm/nodes/DocTableCell.js +18 -0
- package/lib-esm/nodes/DocTableCell.js.map +1 -0
- package/lib-esm/nodes/DocTableRow.js +47 -0
- package/lib-esm/nodes/DocTableRow.js.map +1 -0
- package/lib-esm/plugin/IApiDocumenterPluginManifest.js +4 -0
- package/lib-esm/plugin/IApiDocumenterPluginManifest.js.map +1 -0
- package/lib-esm/plugin/MarkdownDocumenterAccessor.js +26 -0
- package/lib-esm/plugin/MarkdownDocumenterAccessor.js.map +1 -0
- package/lib-esm/plugin/MarkdownDocumenterFeature.js +47 -0
- package/lib-esm/plugin/MarkdownDocumenterFeature.js.map +1 -0
- package/lib-esm/plugin/PluginFeature.js +54 -0
- package/lib-esm/plugin/PluginFeature.js.map +1 -0
- package/lib-esm/plugin/PluginLoader.js +78 -0
- package/lib-esm/plugin/PluginLoader.js.map +1 -0
- package/lib-esm/schemas/api-documenter-template.json +99 -0
- package/lib-esm/schemas/api-documenter.schema.json +47 -0
- package/lib-esm/start.js +12 -0
- package/lib-esm/start.js.map +1 -0
- package/lib-esm/utils/IndentedWriter.js +235 -0
- package/lib-esm/utils/IndentedWriter.js.map +1 -0
- package/lib-esm/utils/ToSdpConvertHelper.js +338 -0
- package/lib-esm/utils/ToSdpConvertHelper.js.map +1 -0
- package/lib-esm/utils/Utilities.js +24 -0
- package/lib-esm/utils/Utilities.js.map +1 -0
- package/lib-esm/yaml/ISDPYamlFile.js +4 -0
- package/lib-esm/yaml/ISDPYamlFile.js.map +1 -0
- package/lib-esm/yaml/IYamlApiFile.js +4 -0
- package/lib-esm/yaml/IYamlApiFile.js.map +1 -0
- package/lib-esm/yaml/IYamlTocFile.js +4 -0
- package/lib-esm/yaml/IYamlTocFile.js.map +1 -0
- package/lib-esm/yaml/typescript.schema.json +643 -0
- package/package.json +35 -9
- /package/{lib → lib-commonjs}/cli/ApiDocumenterCommandLine.js +0 -0
- /package/{lib → lib-commonjs}/cli/ApiDocumenterCommandLine.js.map +0 -0
- /package/{lib → lib-commonjs}/cli/BaseAction.js +0 -0
- /package/{lib → lib-commonjs}/cli/BaseAction.js.map +0 -0
- /package/{lib → lib-commonjs}/cli/GenerateAction.js +0 -0
- /package/{lib → lib-commonjs}/cli/GenerateAction.js.map +0 -0
- /package/{lib → lib-commonjs}/cli/MarkdownAction.js +0 -0
- /package/{lib → lib-commonjs}/cli/MarkdownAction.js.map +0 -0
- /package/{lib → lib-commonjs}/cli/YamlAction.js +0 -0
- /package/{lib → lib-commonjs}/cli/YamlAction.js.map +0 -0
- /package/{lib → lib-commonjs}/documenters/DocumenterConfig.js +0 -0
- /package/{lib → lib-commonjs}/documenters/DocumenterConfig.js.map +0 -0
- /package/{lib → lib-commonjs}/documenters/ExperimentalYamlDocumenter.js +0 -0
- /package/{lib → lib-commonjs}/documenters/ExperimentalYamlDocumenter.js.map +0 -0
- /package/{lib → lib-commonjs}/documenters/IConfigFile.js +0 -0
- /package/{lib → lib-commonjs}/documenters/IConfigFile.js.map +0 -0
- /package/{lib → lib-commonjs}/documenters/MarkdownDocumenter.js +0 -0
- /package/{lib → lib-commonjs}/documenters/MarkdownDocumenter.js.map +0 -0
- /package/{lib → lib-commonjs}/documenters/OfficeYamlDocumenter.js +0 -0
- /package/{lib → lib-commonjs}/documenters/OfficeYamlDocumenter.js.map +0 -0
- /package/{lib → lib-commonjs}/documenters/YamlDocumenter.js +0 -0
- /package/{lib → lib-commonjs}/documenters/YamlDocumenter.js.map +0 -0
- /package/{lib → lib-commonjs}/index.js +0 -0
- /package/{lib → lib-commonjs}/index.js.map +0 -0
- /package/{lib → lib-commonjs}/markdown/CustomMarkdownEmitter.js +0 -0
- /package/{lib → lib-commonjs}/markdown/CustomMarkdownEmitter.js.map +0 -0
- /package/{lib → lib-commonjs}/markdown/MarkdownEmitter.js +0 -0
- /package/{lib → lib-commonjs}/markdown/MarkdownEmitter.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/CustomDocNodeKind.js +0 -0
- /package/{lib → lib-commonjs}/nodes/CustomDocNodeKind.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/DocEmphasisSpan.js +0 -0
- /package/{lib → lib-commonjs}/nodes/DocEmphasisSpan.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/DocHeading.js +0 -0
- /package/{lib → lib-commonjs}/nodes/DocHeading.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/DocNoteBox.js +0 -0
- /package/{lib → lib-commonjs}/nodes/DocNoteBox.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/DocTable.js +0 -0
- /package/{lib → lib-commonjs}/nodes/DocTable.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/DocTableCell.js +0 -0
- /package/{lib → lib-commonjs}/nodes/DocTableCell.js.map +0 -0
- /package/{lib → lib-commonjs}/nodes/DocTableRow.js +0 -0
- /package/{lib → lib-commonjs}/nodes/DocTableRow.js.map +0 -0
- /package/{lib → lib-commonjs}/plugin/IApiDocumenterPluginManifest.js +0 -0
- /package/{lib → lib-commonjs}/plugin/IApiDocumenterPluginManifest.js.map +0 -0
- /package/{lib → lib-commonjs}/plugin/MarkdownDocumenterAccessor.js +0 -0
- /package/{lib → lib-commonjs}/plugin/MarkdownDocumenterAccessor.js.map +0 -0
- /package/{lib → lib-commonjs}/plugin/MarkdownDocumenterFeature.js +0 -0
- /package/{lib → lib-commonjs}/plugin/MarkdownDocumenterFeature.js.map +0 -0
- /package/{lib → lib-commonjs}/plugin/PluginFeature.js +0 -0
- /package/{lib → lib-commonjs}/plugin/PluginFeature.js.map +0 -0
- /package/{lib → lib-commonjs}/plugin/PluginLoader.js +0 -0
- /package/{lib → lib-commonjs}/plugin/PluginLoader.js.map +0 -0
- /package/{lib → lib-commonjs}/schemas/api-documenter-template.json +0 -0
- /package/{lib → lib-commonjs}/schemas/api-documenter.schema.json +0 -0
- /package/{lib → lib-commonjs}/start.js +0 -0
- /package/{lib → lib-commonjs}/start.js.map +0 -0
- /package/{lib → lib-commonjs}/utils/IndentedWriter.js +0 -0
- /package/{lib → lib-commonjs}/utils/IndentedWriter.js.map +0 -0
- /package/{lib → lib-commonjs}/utils/ToSdpConvertHelper.js +0 -0
- /package/{lib → lib-commonjs}/utils/ToSdpConvertHelper.js.map +0 -0
- /package/{lib → lib-commonjs}/utils/Utilities.js +0 -0
- /package/{lib → lib-commonjs}/utils/Utilities.js.map +0 -0
- /package/{lib → lib-commonjs}/yaml/ISDPYamlFile.js +0 -0
- /package/{lib → lib-commonjs}/yaml/ISDPYamlFile.js.map +0 -0
- /package/{lib → lib-commonjs}/yaml/IYamlApiFile.js +0 -0
- /package/{lib → lib-commonjs}/yaml/IYamlApiFile.js.map +0 -0
- /package/{lib → lib-commonjs}/yaml/IYamlTocFile.js +0 -0
- /package/{lib → lib-commonjs}/yaml/IYamlTocFile.js.map +0 -0
- /package/{lib → lib-commonjs}/yaml/typescript.schema.json +0 -0
- /package/{lib → lib-dts}/cli/ApiDocumenterCommandLine.d.ts +0 -0
- /package/{lib → lib-dts}/cli/ApiDocumenterCommandLine.d.ts.map +0 -0
- /package/{lib → lib-dts}/cli/BaseAction.d.ts +0 -0
- /package/{lib → lib-dts}/cli/BaseAction.d.ts.map +0 -0
- /package/{lib → lib-dts}/cli/GenerateAction.d.ts +0 -0
- /package/{lib → lib-dts}/cli/GenerateAction.d.ts.map +0 -0
- /package/{lib → lib-dts}/cli/MarkdownAction.d.ts +0 -0
- /package/{lib → lib-dts}/cli/MarkdownAction.d.ts.map +0 -0
- /package/{lib → lib-dts}/cli/YamlAction.d.ts +0 -0
- /package/{lib → lib-dts}/cli/YamlAction.d.ts.map +0 -0
- /package/{lib → lib-dts}/documenters/DocumenterConfig.d.ts +0 -0
- /package/{lib → lib-dts}/documenters/DocumenterConfig.d.ts.map +0 -0
- /package/{lib → lib-dts}/documenters/ExperimentalYamlDocumenter.d.ts +0 -0
- /package/{lib → lib-dts}/documenters/ExperimentalYamlDocumenter.d.ts.map +0 -0
- /package/{lib → lib-dts}/documenters/IConfigFile.d.ts +0 -0
- /package/{lib → lib-dts}/documenters/IConfigFile.d.ts.map +0 -0
- /package/{lib → lib-dts}/documenters/MarkdownDocumenter.d.ts +0 -0
- /package/{lib → lib-dts}/documenters/MarkdownDocumenter.d.ts.map +0 -0
- /package/{lib → lib-dts}/documenters/OfficeYamlDocumenter.d.ts +0 -0
- /package/{lib → lib-dts}/documenters/OfficeYamlDocumenter.d.ts.map +0 -0
- /package/{lib → lib-dts}/documenters/YamlDocumenter.d.ts +0 -0
- /package/{lib → lib-dts}/documenters/YamlDocumenter.d.ts.map +0 -0
- /package/{lib → lib-dts}/index.d.ts +0 -0
- /package/{lib → lib-dts}/index.d.ts.map +0 -0
- /package/{lib → lib-dts}/markdown/CustomMarkdownEmitter.d.ts +0 -0
- /package/{lib → lib-dts}/markdown/CustomMarkdownEmitter.d.ts.map +0 -0
- /package/{lib → lib-dts}/markdown/MarkdownEmitter.d.ts +0 -0
- /package/{lib → lib-dts}/markdown/MarkdownEmitter.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/CustomDocNodeKind.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/CustomDocNodeKind.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/DocEmphasisSpan.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/DocEmphasisSpan.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/DocHeading.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/DocHeading.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/DocNoteBox.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/DocNoteBox.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/DocTable.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/DocTable.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/DocTableCell.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/DocTableCell.d.ts.map +0 -0
- /package/{lib → lib-dts}/nodes/DocTableRow.d.ts +0 -0
- /package/{lib → lib-dts}/nodes/DocTableRow.d.ts.map +0 -0
- /package/{lib → lib-dts}/plugin/IApiDocumenterPluginManifest.d.ts +0 -0
- /package/{lib → lib-dts}/plugin/IApiDocumenterPluginManifest.d.ts.map +0 -0
- /package/{lib → lib-dts}/plugin/MarkdownDocumenterAccessor.d.ts +0 -0
- /package/{lib → lib-dts}/plugin/MarkdownDocumenterAccessor.d.ts.map +0 -0
- /package/{lib → lib-dts}/plugin/MarkdownDocumenterFeature.d.ts +0 -0
- /package/{lib → lib-dts}/plugin/MarkdownDocumenterFeature.d.ts.map +0 -0
- /package/{lib → lib-dts}/plugin/PluginFeature.d.ts +0 -0
- /package/{lib → lib-dts}/plugin/PluginFeature.d.ts.map +0 -0
- /package/{lib → lib-dts}/plugin/PluginLoader.d.ts +0 -0
- /package/{lib → lib-dts}/plugin/PluginLoader.d.ts.map +0 -0
- /package/{lib → lib-dts}/start.d.ts +0 -0
- /package/{lib → lib-dts}/start.d.ts.map +0 -0
- /package/{lib → lib-dts}/utils/IndentedWriter.d.ts +0 -0
- /package/{lib → lib-dts}/utils/IndentedWriter.d.ts.map +0 -0
- /package/{lib → lib-dts}/utils/ToSdpConvertHelper.d.ts +0 -0
- /package/{lib → lib-dts}/utils/ToSdpConvertHelper.d.ts.map +0 -0
- /package/{lib → lib-dts}/utils/Utilities.d.ts +0 -0
- /package/{lib → lib-dts}/utils/Utilities.d.ts.map +0 -0
- /package/{lib → lib-dts}/yaml/ISDPYamlFile.d.ts +0 -0
- /package/{lib → lib-dts}/yaml/ISDPYamlFile.d.ts.map +0 -0
- /package/{lib → lib-dts}/yaml/IYamlApiFile.d.ts +0 -0
- /package/{lib → lib-dts}/yaml/IYamlApiFile.d.ts.map +0 -0
- /package/{lib → lib-dts}/yaml/IYamlTocFile.d.ts +0 -0
- /package/{lib → lib-dts}/yaml/IYamlTocFile.d.ts.map +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "API Documenter Configuration",
|
|
3
|
+
"description": "Describes how the API Documenter tool will process a project.",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"$schema": {
|
|
7
|
+
"description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.",
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
"outputTarget": {
|
|
12
|
+
"description": "Specifies what type of documentation will be generated",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"enum": ["docfx", "markdown"]
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
"newlineKind": {
|
|
18
|
+
"description": "Specifies what type of newlines API Documenter should use when writing output files. By default, the output files will be written with Windows-style newlines. To use POSIX-style newlines, specify \"lf\" instead. To use the OS's default newline kind, specify \"os\".",
|
|
19
|
+
"type": "string",
|
|
20
|
+
"enum": ["crlf", "lf", "os"],
|
|
21
|
+
"default": "crlf"
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
"newDocfxNamespaces": {
|
|
25
|
+
"description": "This enables an experimental feature that will be officially released with the next major version of API Documenter. It requires DocFX 2.46 or newer. It enables documentation for namespaces and adds them to the table of contents. This will also affect file layout as namespaced items will be nested under a directory for the namespace instead of just within the package.",
|
|
26
|
+
"type": "boolean"
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
"plugins": {
|
|
30
|
+
"description": "Specifies plugin packages to be loaded",
|
|
31
|
+
"type": "array"
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
"tableOfContents": {
|
|
35
|
+
"description": "Configures how the table of contents is generated.",
|
|
36
|
+
"type": "object",
|
|
37
|
+
"additionalProperties": true
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"showInheritedMembers": {
|
|
41
|
+
"description": "Specifies whether inherited members should also be shown on an API item's page.",
|
|
42
|
+
"type": "boolean"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
"additionalProperties": false
|
|
47
|
+
}
|
package/lib-esm/start.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
2
|
+
// See LICENSE in the project root for license information.
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import { PackageJsonLookup } from '@rushstack/node-core-library';
|
|
5
|
+
import { Colorize } from '@rushstack/terminal';
|
|
6
|
+
import { ApiDocumenterCommandLine } from './cli/ApiDocumenterCommandLine';
|
|
7
|
+
const myPackageVersion = PackageJsonLookup.loadOwnPackageJson(__dirname).version;
|
|
8
|
+
console.log(os.EOL +
|
|
9
|
+
Colorize.bold(`api-documenter ${myPackageVersion} ` + Colorize.cyan(' - https://api-extractor.com/') + os.EOL));
|
|
10
|
+
const parser = new ApiDocumenterCommandLine();
|
|
11
|
+
parser.executeAsync().catch(console.error); // CommandLineParser.executeAsync() should never reject the promise
|
|
12
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAE3D,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,MAAM,gBAAgB,GAAW,iBAAiB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;AAEzF,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG;IACJ,QAAQ,CAAC,IAAI,CACX,kBAAkB,gBAAgB,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,+BAA+B,CAAC,GAAG,EAAE,CAAC,GAAG,CAChG,CACJ,CAAC;AAEF,MAAM,MAAM,GAA6B,IAAI,wBAAwB,EAAE,CAAC;AAExE,MAAM,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,mEAAmE","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport * as os from 'node:os';\n\nimport { PackageJsonLookup } from '@rushstack/node-core-library';\nimport { Colorize } from '@rushstack/terminal';\n\nimport { ApiDocumenterCommandLine } from './cli/ApiDocumenterCommandLine';\n\nconst myPackageVersion: string = PackageJsonLookup.loadOwnPackageJson(__dirname).version;\n\nconsole.log(\n os.EOL +\n Colorize.bold(\n `api-documenter ${myPackageVersion} ` + Colorize.cyan(' - https://api-extractor.com/') + os.EOL\n )\n);\n\nconst parser: ApiDocumenterCommandLine = new ApiDocumenterCommandLine();\n\nparser.executeAsync().catch(console.error); // CommandLineParser.executeAsync() should never reject the promise\n"]}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
2
|
+
// See LICENSE in the project root for license information.
|
|
3
|
+
import { StringBuilder } from '@rushstack/node-core-library';
|
|
4
|
+
/**
|
|
5
|
+
* A utility for writing indented text.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
*
|
|
9
|
+
* Note that the indentation is inserted at the last possible opportunity.
|
|
10
|
+
* For example, this code...
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* writer.write('begin\n');
|
|
14
|
+
* writer.increaseIndent();
|
|
15
|
+
* writer.write('one\ntwo\n');
|
|
16
|
+
* writer.decreaseIndent();
|
|
17
|
+
* writer.increaseIndent();
|
|
18
|
+
* writer.decreaseIndent();
|
|
19
|
+
* writer.write('end');
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ...would produce this output:
|
|
23
|
+
*
|
|
24
|
+
* ```
|
|
25
|
+
* begin
|
|
26
|
+
* one
|
|
27
|
+
* two
|
|
28
|
+
* end
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export class IndentedWriter {
|
|
32
|
+
constructor(builder) {
|
|
33
|
+
/**
|
|
34
|
+
* The text characters used to create one level of indentation.
|
|
35
|
+
* Two spaces by default.
|
|
36
|
+
*/
|
|
37
|
+
this.defaultIndentPrefix = ' ';
|
|
38
|
+
this._builder = builder === undefined ? new StringBuilder() : builder;
|
|
39
|
+
this._latestChunk = undefined;
|
|
40
|
+
this._previousChunk = undefined;
|
|
41
|
+
this._atStartOfLine = true;
|
|
42
|
+
this._indentStack = [];
|
|
43
|
+
this._indentText = '';
|
|
44
|
+
this._beforeStack = [];
|
|
45
|
+
this._isWritingBeforeStack = false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Retrieves the output that was built so far.
|
|
49
|
+
*/
|
|
50
|
+
getText() {
|
|
51
|
+
return this._builder.toString();
|
|
52
|
+
}
|
|
53
|
+
toString() {
|
|
54
|
+
return this.getText();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Increases the indentation. Normally the indentation is two spaces,
|
|
58
|
+
* however an arbitrary prefix can optional be specified. (For example,
|
|
59
|
+
* the prefix could be "// " to indent and comment simultaneously.)
|
|
60
|
+
* Each call to IndentedWriter.increaseIndent() must be followed by a
|
|
61
|
+
* corresponding call to IndentedWriter.decreaseIndent().
|
|
62
|
+
*/
|
|
63
|
+
increaseIndent(indentPrefix) {
|
|
64
|
+
this._indentStack.push(indentPrefix !== undefined ? indentPrefix : this.defaultIndentPrefix);
|
|
65
|
+
this._updateIndentText();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Decreases the indentation, reverting the effect of the corresponding call
|
|
69
|
+
* to IndentedWriter.increaseIndent().
|
|
70
|
+
*/
|
|
71
|
+
decreaseIndent() {
|
|
72
|
+
this._indentStack.pop();
|
|
73
|
+
this._updateIndentText();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A shorthand for ensuring that increaseIndent()/decreaseIndent() occur
|
|
77
|
+
* in pairs.
|
|
78
|
+
*/
|
|
79
|
+
indentScope(scope, indentPrefix) {
|
|
80
|
+
this.increaseIndent(indentPrefix);
|
|
81
|
+
scope();
|
|
82
|
+
this.decreaseIndent();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Adds a newline if the file pointer is not already at the start of the line (or start of the stream).
|
|
86
|
+
*/
|
|
87
|
+
ensureNewLine() {
|
|
88
|
+
const lastCharacter = this.peekLastCharacter();
|
|
89
|
+
if (lastCharacter !== '\n' && lastCharacter !== '') {
|
|
90
|
+
this._writeNewLine();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Adds up to two newlines to ensure that there is a blank line above the current line.
|
|
95
|
+
*/
|
|
96
|
+
ensureSkippedLine() {
|
|
97
|
+
if (this.peekLastCharacter() !== '\n') {
|
|
98
|
+
this._writeNewLine();
|
|
99
|
+
}
|
|
100
|
+
const secondLastCharacter = this.peekSecondLastCharacter();
|
|
101
|
+
if (secondLastCharacter !== '\n' && secondLastCharacter !== '') {
|
|
102
|
+
this._writeNewLine();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns the last character that was written, or an empty string if no characters have been written yet.
|
|
107
|
+
*/
|
|
108
|
+
peekLastCharacter() {
|
|
109
|
+
if (this._latestChunk !== undefined) {
|
|
110
|
+
return this._latestChunk.substr(-1, 1);
|
|
111
|
+
}
|
|
112
|
+
return '';
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Returns the second to last character that was written, or an empty string if less than one characters
|
|
116
|
+
* have been written yet.
|
|
117
|
+
*/
|
|
118
|
+
peekSecondLastCharacter() {
|
|
119
|
+
if (this._latestChunk !== undefined) {
|
|
120
|
+
if (this._latestChunk.length > 1) {
|
|
121
|
+
return this._latestChunk.substr(-2, 1);
|
|
122
|
+
}
|
|
123
|
+
if (this._previousChunk !== undefined) {
|
|
124
|
+
return this._previousChunk.substr(-1, 1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Writes `before` and `after` messages if and only if `mayWrite` writes anything.
|
|
131
|
+
*
|
|
132
|
+
* If `mayWrite` writes "CONTENT", this method will write "<before>CONTENT<after>".
|
|
133
|
+
* If `mayWrite` writes nothing, this method will write nothing.
|
|
134
|
+
*/
|
|
135
|
+
writeTentative(before, after, mayWrite) {
|
|
136
|
+
this._beforeStack.push(before);
|
|
137
|
+
// If this function writes anything, then _all_ messages in the "before stack" will also be
|
|
138
|
+
// written. This means that the stack will be empty (as when we write a message from the stack,
|
|
139
|
+
// we remove it from the stack).
|
|
140
|
+
mayWrite();
|
|
141
|
+
// If the stack is not empty, it means that `mayWrite` didn't write anything. Pop the last-
|
|
142
|
+
// added message from the stack, we'll never write it. Otherwise, if the stack is empty, then
|
|
143
|
+
// write the "after" message.
|
|
144
|
+
if (this._beforeStack.length > 0) {
|
|
145
|
+
this._beforeStack.pop();
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
this.write(after);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Writes some text to the internal string buffer, applying indentation according
|
|
153
|
+
* to the current indentation level. If the string contains multiple newlines,
|
|
154
|
+
* each line will be indented separately.
|
|
155
|
+
*/
|
|
156
|
+
write(message) {
|
|
157
|
+
if (message.length === 0) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (!this._isWritingBeforeStack) {
|
|
161
|
+
this._writeBeforeStack();
|
|
162
|
+
}
|
|
163
|
+
// If there are no newline characters, then append the string verbatim
|
|
164
|
+
if (!/[\r\n]/.test(message)) {
|
|
165
|
+
this._writeLinePart(message);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Otherwise split the lines and write each one individually
|
|
169
|
+
let first = true;
|
|
170
|
+
for (const linePart of message.split('\n')) {
|
|
171
|
+
if (!first) {
|
|
172
|
+
this._writeNewLine();
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
first = false;
|
|
176
|
+
}
|
|
177
|
+
if (linePart) {
|
|
178
|
+
this._writeLinePart(linePart.replace(/[\r]/g, ''));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* A shorthand for writing an optional message, followed by a newline.
|
|
184
|
+
* Indentation is applied following the semantics of IndentedWriter.write().
|
|
185
|
+
*/
|
|
186
|
+
writeLine(message = '') {
|
|
187
|
+
if (message.length > 0) {
|
|
188
|
+
this.write(message);
|
|
189
|
+
}
|
|
190
|
+
else if (!this._isWritingBeforeStack) {
|
|
191
|
+
this._writeBeforeStack();
|
|
192
|
+
}
|
|
193
|
+
this._writeNewLine();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Writes a string that does not contain any newline characters.
|
|
197
|
+
*/
|
|
198
|
+
_writeLinePart(message) {
|
|
199
|
+
if (message.length > 0) {
|
|
200
|
+
if (this._atStartOfLine && this._indentText.length > 0) {
|
|
201
|
+
this._write(this._indentText);
|
|
202
|
+
}
|
|
203
|
+
this._write(message);
|
|
204
|
+
this._atStartOfLine = false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
_writeNewLine() {
|
|
208
|
+
if (this._atStartOfLine && this._indentText.length > 0) {
|
|
209
|
+
this._write(this._indentText);
|
|
210
|
+
}
|
|
211
|
+
this._write('\n');
|
|
212
|
+
this._atStartOfLine = true;
|
|
213
|
+
}
|
|
214
|
+
_write(s) {
|
|
215
|
+
this._previousChunk = this._latestChunk;
|
|
216
|
+
this._latestChunk = s;
|
|
217
|
+
this._builder.append(s);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Writes all messages in our before stack, processing them in FIFO order. This stack is
|
|
221
|
+
* populated by the `writeTentative` method.
|
|
222
|
+
*/
|
|
223
|
+
_writeBeforeStack() {
|
|
224
|
+
this._isWritingBeforeStack = true;
|
|
225
|
+
for (const message of this._beforeStack) {
|
|
226
|
+
this.write(message);
|
|
227
|
+
}
|
|
228
|
+
this._isWritingBeforeStack = false;
|
|
229
|
+
this._beforeStack = [];
|
|
230
|
+
}
|
|
231
|
+
_updateIndentText() {
|
|
232
|
+
this._indentText = this._indentStack.join('');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=IndentedWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndentedWriter.js","sourceRoot":"","sources":["../../src/utils/IndentedWriter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { StringBuilder, type IStringBuilder } from '@rushstack/node-core-library';\n\n/**\n * A utility for writing indented text.\n *\n * @remarks\n *\n * Note that the indentation is inserted at the last possible opportunity.\n * For example, this code...\n *\n * ```ts\n * writer.write('begin\\n');\n * writer.increaseIndent();\n * writer.write('one\\ntwo\\n');\n * writer.decreaseIndent();\n * writer.increaseIndent();\n * writer.decreaseIndent();\n * writer.write('end');\n * ```\n *\n * ...would produce this output:\n *\n * ```\n * begin\n * one\n * two\n * end\n * ```\n */\nexport class IndentedWriter {\n /**\n * The text characters used to create one level of indentation.\n * Two spaces by default.\n */\n public defaultIndentPrefix: string = ' ';\n\n private readonly _builder: IStringBuilder;\n\n private _latestChunk: string | undefined;\n private _previousChunk: string | undefined;\n private _atStartOfLine: boolean;\n\n private readonly _indentStack: string[];\n private _indentText: string;\n\n private _beforeStack: string[];\n private _isWritingBeforeStack: boolean;\n\n public constructor(builder?: IStringBuilder) {\n this._builder = builder === undefined ? new StringBuilder() : builder;\n\n this._latestChunk = undefined;\n this._previousChunk = undefined;\n this._atStartOfLine = true;\n\n this._indentStack = [];\n this._indentText = '';\n\n this._beforeStack = [];\n this._isWritingBeforeStack = false;\n }\n\n /**\n * Retrieves the output that was built so far.\n */\n public getText(): string {\n return this._builder.toString();\n }\n\n public toString(): string {\n return this.getText();\n }\n\n /**\n * Increases the indentation. Normally the indentation is two spaces,\n * however an arbitrary prefix can optional be specified. (For example,\n * the prefix could be \"// \" to indent and comment simultaneously.)\n * Each call to IndentedWriter.increaseIndent() must be followed by a\n * corresponding call to IndentedWriter.decreaseIndent().\n */\n public increaseIndent(indentPrefix?: string): void {\n this._indentStack.push(indentPrefix !== undefined ? indentPrefix : this.defaultIndentPrefix);\n this._updateIndentText();\n }\n\n /**\n * Decreases the indentation, reverting the effect of the corresponding call\n * to IndentedWriter.increaseIndent().\n */\n public decreaseIndent(): void {\n this._indentStack.pop();\n this._updateIndentText();\n }\n\n /**\n * A shorthand for ensuring that increaseIndent()/decreaseIndent() occur\n * in pairs.\n */\n public indentScope(scope: () => void, indentPrefix?: string): void {\n this.increaseIndent(indentPrefix);\n scope();\n this.decreaseIndent();\n }\n\n /**\n * Adds a newline if the file pointer is not already at the start of the line (or start of the stream).\n */\n public ensureNewLine(): void {\n const lastCharacter: string = this.peekLastCharacter();\n if (lastCharacter !== '\\n' && lastCharacter !== '') {\n this._writeNewLine();\n }\n }\n\n /**\n * Adds up to two newlines to ensure that there is a blank line above the current line.\n */\n public ensureSkippedLine(): void {\n if (this.peekLastCharacter() !== '\\n') {\n this._writeNewLine();\n }\n\n const secondLastCharacter: string = this.peekSecondLastCharacter();\n if (secondLastCharacter !== '\\n' && secondLastCharacter !== '') {\n this._writeNewLine();\n }\n }\n\n /**\n * Returns the last character that was written, or an empty string if no characters have been written yet.\n */\n public peekLastCharacter(): string {\n if (this._latestChunk !== undefined) {\n return this._latestChunk.substr(-1, 1);\n }\n return '';\n }\n\n /**\n * Returns the second to last character that was written, or an empty string if less than one characters\n * have been written yet.\n */\n public peekSecondLastCharacter(): string {\n if (this._latestChunk !== undefined) {\n if (this._latestChunk.length > 1) {\n return this._latestChunk.substr(-2, 1);\n }\n if (this._previousChunk !== undefined) {\n return this._previousChunk.substr(-1, 1);\n }\n }\n return '';\n }\n\n /**\n * Writes `before` and `after` messages if and only if `mayWrite` writes anything.\n *\n * If `mayWrite` writes \"CONTENT\", this method will write \"<before>CONTENT<after>\".\n * If `mayWrite` writes nothing, this method will write nothing.\n */\n public writeTentative(before: string, after: string, mayWrite: () => void): void {\n this._beforeStack.push(before);\n\n // If this function writes anything, then _all_ messages in the \"before stack\" will also be\n // written. This means that the stack will be empty (as when we write a message from the stack,\n // we remove it from the stack).\n mayWrite();\n\n // If the stack is not empty, it means that `mayWrite` didn't write anything. Pop the last-\n // added message from the stack, we'll never write it. Otherwise, if the stack is empty, then\n // write the \"after\" message.\n if (this._beforeStack.length > 0) {\n this._beforeStack.pop();\n } else {\n this.write(after);\n }\n }\n\n /**\n * Writes some text to the internal string buffer, applying indentation according\n * to the current indentation level. If the string contains multiple newlines,\n * each line will be indented separately.\n */\n public write(message: string): void {\n if (message.length === 0) {\n return;\n }\n\n if (!this._isWritingBeforeStack) {\n this._writeBeforeStack();\n }\n\n // If there are no newline characters, then append the string verbatim\n if (!/[\\r\\n]/.test(message)) {\n this._writeLinePart(message);\n return;\n }\n\n // Otherwise split the lines and write each one individually\n let first: boolean = true;\n for (const linePart of message.split('\\n')) {\n if (!first) {\n this._writeNewLine();\n } else {\n first = false;\n }\n if (linePart) {\n this._writeLinePart(linePart.replace(/[\\r]/g, ''));\n }\n }\n }\n\n /**\n * A shorthand for writing an optional message, followed by a newline.\n * Indentation is applied following the semantics of IndentedWriter.write().\n */\n public writeLine(message: string = ''): void {\n if (message.length > 0) {\n this.write(message);\n } else if (!this._isWritingBeforeStack) {\n this._writeBeforeStack();\n }\n\n this._writeNewLine();\n }\n\n /**\n * Writes a string that does not contain any newline characters.\n */\n private _writeLinePart(message: string): void {\n if (message.length > 0) {\n if (this._atStartOfLine && this._indentText.length > 0) {\n this._write(this._indentText);\n }\n this._write(message);\n this._atStartOfLine = false;\n }\n }\n\n private _writeNewLine(): void {\n if (this._atStartOfLine && this._indentText.length > 0) {\n this._write(this._indentText);\n }\n\n this._write('\\n');\n this._atStartOfLine = true;\n }\n\n private _write(s: string): void {\n this._previousChunk = this._latestChunk;\n this._latestChunk = s;\n this._builder.append(s);\n }\n\n /**\n * Writes all messages in our before stack, processing them in FIFO order. This stack is\n * populated by the `writeTentative` method.\n */\n private _writeBeforeStack(): void {\n this._isWritingBeforeStack = true;\n\n for (const message of this._beforeStack) {\n this.write(message);\n }\n\n this._isWritingBeforeStack = false;\n this._beforeStack = [];\n }\n\n private _updateIndentText(): void {\n this._indentText = this._indentStack.join('');\n }\n}\n"]}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
2
|
+
// See LICENSE in the project root for license information.
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { FileSystem, Encoding, NewlineKind } from '@rushstack/node-core-library';
|
|
5
|
+
export function convertUDPYamlToSDP(folderPath) {
|
|
6
|
+
convert(folderPath, folderPath);
|
|
7
|
+
}
|
|
8
|
+
function convert(inputPath, outputPath) {
|
|
9
|
+
console.log();
|
|
10
|
+
if (!FileSystem.exists(inputPath)) {
|
|
11
|
+
console.error(`input path: ${inputPath} is not exist`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
FileSystem.readFolderItemNames(inputPath).forEach((name) => {
|
|
15
|
+
const fpath = path.join(inputPath, name);
|
|
16
|
+
if (FileSystem.getStatistics(fpath).isFile()) {
|
|
17
|
+
// only convert yaml
|
|
18
|
+
if (!name.endsWith('.yml')) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// parse file
|
|
22
|
+
const yamlContent = FileSystem.readFile(fpath, { encoding: Encoding.Utf8 });
|
|
23
|
+
// only convert universalreference yaml
|
|
24
|
+
const isLegacyYaml = yamlContent.startsWith('### YamlMime:UniversalReference');
|
|
25
|
+
if (!isLegacyYaml) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.log(`convert file ${fpath} from udp to sdp`);
|
|
29
|
+
const file = yaml.load(yamlContent);
|
|
30
|
+
const result = convertToSDP(file);
|
|
31
|
+
if (result && result.model) {
|
|
32
|
+
const stringified = `### YamlMime:TS${result.type}\n${yaml.dump(result.model, {
|
|
33
|
+
lineWidth: 120
|
|
34
|
+
})}`;
|
|
35
|
+
FileSystem.writeFile(`${outputPath}/${name}`, stringified, {
|
|
36
|
+
convertLineEndings: NewlineKind.CrLf,
|
|
37
|
+
ensureFolderExists: true
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.log('not target file ', fpath);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// read contents
|
|
46
|
+
convert(fpath, path.join(outputPath, name));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function convertToPackageSDP(transfomredClass) {
|
|
51
|
+
const element = transfomredClass.items[0];
|
|
52
|
+
const packageModel = {
|
|
53
|
+
uid: element.uid,
|
|
54
|
+
name: element.name,
|
|
55
|
+
type: 'package'
|
|
56
|
+
};
|
|
57
|
+
if (element.summary) {
|
|
58
|
+
packageModel.summary = element.summary;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
packageModel.summary = '';
|
|
62
|
+
}
|
|
63
|
+
// search in children
|
|
64
|
+
if (element.children) {
|
|
65
|
+
element.children.forEach((child) => {
|
|
66
|
+
if (child.endsWith(':class')) {
|
|
67
|
+
assignPackageModelFields(packageModel, 'classes', child);
|
|
68
|
+
}
|
|
69
|
+
else if (child.endsWith(':interface')) {
|
|
70
|
+
assignPackageModelFields(packageModel, 'interfaces', child);
|
|
71
|
+
}
|
|
72
|
+
else if (child.endsWith(':enum')) {
|
|
73
|
+
assignPackageModelFields(packageModel, 'enums', child);
|
|
74
|
+
}
|
|
75
|
+
else if (child.endsWith(':type')) {
|
|
76
|
+
assignPackageModelFields(packageModel, 'typeAliases', child);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// console.log("other type: ", child)
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
for (let i = 1; i < transfomredClass.items.length; i++) {
|
|
84
|
+
const ele = transfomredClass.items[i];
|
|
85
|
+
switch (ele.type) {
|
|
86
|
+
case 'typealias':
|
|
87
|
+
// need generate typeAlias file for this
|
|
88
|
+
break;
|
|
89
|
+
case 'function':
|
|
90
|
+
if (!packageModel.functions) {
|
|
91
|
+
packageModel.functions = [];
|
|
92
|
+
}
|
|
93
|
+
packageModel.functions.push(convertToFunctionSDP(ele, element.uid, transfomredClass));
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
// console.log(transfomredClass.items[0].name)
|
|
97
|
+
console.log('[warning] not applied type(package): ', ele.type);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return packageModel;
|
|
101
|
+
}
|
|
102
|
+
function assignPackageModelFields(packageModel, name, uid) {
|
|
103
|
+
if (!packageModel[name]) {
|
|
104
|
+
packageModel[name] = [];
|
|
105
|
+
}
|
|
106
|
+
packageModel[name].push(uid);
|
|
107
|
+
}
|
|
108
|
+
function convertToSDP(transfomredClass) {
|
|
109
|
+
const element = transfomredClass.items[0];
|
|
110
|
+
switch (element.type) {
|
|
111
|
+
case 'class':
|
|
112
|
+
case 'interface':
|
|
113
|
+
return {
|
|
114
|
+
model: convertToTypeSDP(transfomredClass, element.type === 'class'),
|
|
115
|
+
type: 'Type'
|
|
116
|
+
};
|
|
117
|
+
case 'enum':
|
|
118
|
+
if (transfomredClass.items.length < 2) {
|
|
119
|
+
console.log(`[warning] enum ${element.uid}/${element.name} does not have fields`);
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return { model: convertToEnumSDP(transfomredClass), type: 'Enum' };
|
|
123
|
+
case 'typealias':
|
|
124
|
+
return { model: convertToTypeAliasSDP(element, transfomredClass), type: 'TypeAlias' };
|
|
125
|
+
case 'package':
|
|
126
|
+
return {
|
|
127
|
+
model: convertToPackageSDP(transfomredClass),
|
|
128
|
+
type: 'Package'
|
|
129
|
+
};
|
|
130
|
+
default:
|
|
131
|
+
console.log('not applied type: ', element.type);
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function convertToEnumSDP(transfomredClass) {
|
|
136
|
+
const element = transfomredClass.items[0];
|
|
137
|
+
const fields = [];
|
|
138
|
+
for (let i = 1; i < transfomredClass.items.length; i++) {
|
|
139
|
+
const ele = transfomredClass.items[i];
|
|
140
|
+
const field = {
|
|
141
|
+
name: ele.name,
|
|
142
|
+
uid: ele.uid,
|
|
143
|
+
package: element.package
|
|
144
|
+
};
|
|
145
|
+
if (ele.summary) {
|
|
146
|
+
field.summary = ele.summary;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
field.summary = '';
|
|
150
|
+
}
|
|
151
|
+
if (ele.numericValue) {
|
|
152
|
+
field.value = ele.numericValue;
|
|
153
|
+
}
|
|
154
|
+
fields.push(field);
|
|
155
|
+
}
|
|
156
|
+
const result = {
|
|
157
|
+
...convertCommonYamlModel(element, element.package, transfomredClass),
|
|
158
|
+
fields: fields
|
|
159
|
+
};
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
function convertToTypeAliasSDP(element, transfomredClass) {
|
|
163
|
+
const result = {
|
|
164
|
+
...convertCommonYamlModel(element, element.package, transfomredClass)
|
|
165
|
+
};
|
|
166
|
+
if (element.syntax) {
|
|
167
|
+
result.syntax = element.syntax.content;
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
function convertToTypeSDP(transfomredClass, isClass) {
|
|
172
|
+
const element = transfomredClass.items[0];
|
|
173
|
+
const constructors = [];
|
|
174
|
+
const properties = [];
|
|
175
|
+
const methods = [];
|
|
176
|
+
const events = [];
|
|
177
|
+
for (let i = 1; i < transfomredClass.items.length; i++) {
|
|
178
|
+
const ele = transfomredClass.items[i];
|
|
179
|
+
const item = convertCommonYamlModel(ele, element.package, transfomredClass);
|
|
180
|
+
if (ele.type === 'constructor') {
|
|
181
|
+
// interface does not need this field
|
|
182
|
+
if (isClass) {
|
|
183
|
+
constructors.push(item);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else if (ele.type === 'property') {
|
|
187
|
+
properties.push(item);
|
|
188
|
+
}
|
|
189
|
+
else if (ele.type === 'method') {
|
|
190
|
+
methods.push(item);
|
|
191
|
+
}
|
|
192
|
+
else if (ele.type === 'event') {
|
|
193
|
+
events.push(item);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.log(`[warning] ${ele.uid}#${ele.name} is not applied sub type ${ele.type} for type yaml`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const result = {
|
|
200
|
+
...convertCommonYamlModel(element, element.package, transfomredClass),
|
|
201
|
+
type: isClass ? 'class' : 'interface'
|
|
202
|
+
};
|
|
203
|
+
delete result.syntax;
|
|
204
|
+
if (constructors.length > 0) {
|
|
205
|
+
result.constructors = constructors;
|
|
206
|
+
}
|
|
207
|
+
if (properties.length > 0) {
|
|
208
|
+
result.properties = properties;
|
|
209
|
+
}
|
|
210
|
+
if (methods.length > 0) {
|
|
211
|
+
result.methods = methods;
|
|
212
|
+
}
|
|
213
|
+
if (events.length > 0) {
|
|
214
|
+
result.events = events;
|
|
215
|
+
}
|
|
216
|
+
if (element.extends && element.extends.length > 0) {
|
|
217
|
+
result.extends = convertSelfTypeToXref(element.extends[0], transfomredClass);
|
|
218
|
+
}
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
function convertToFunctionSDP(element, packageName, transfomredClass) {
|
|
222
|
+
const model = convertCommonYamlModel(element, packageName, transfomredClass);
|
|
223
|
+
// don't need these fields
|
|
224
|
+
delete model.fullName;
|
|
225
|
+
return model;
|
|
226
|
+
}
|
|
227
|
+
function convertCommonYamlModel(element, packageName, transfomredClass) {
|
|
228
|
+
var _a;
|
|
229
|
+
const result = {
|
|
230
|
+
name: element.name,
|
|
231
|
+
uid: element.uid,
|
|
232
|
+
package: packageName
|
|
233
|
+
};
|
|
234
|
+
if (element.fullName) {
|
|
235
|
+
result.fullName = element.fullName;
|
|
236
|
+
}
|
|
237
|
+
if (element.summary) {
|
|
238
|
+
result.summary = element.summary;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
result.summary = '';
|
|
242
|
+
}
|
|
243
|
+
// because mustache meet same variable in different level
|
|
244
|
+
// such as: { "pre": true, "list": [{}]}
|
|
245
|
+
// if item in list wants to use pre but the pre is not assigned, it will use outer pre field.
|
|
246
|
+
// so, there need to set below variable explict
|
|
247
|
+
if (element.remarks) {
|
|
248
|
+
result.remarks = element.remarks;
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
result.remarks = '';
|
|
252
|
+
}
|
|
253
|
+
if (element.example) {
|
|
254
|
+
result.example = element.example;
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
result.example = [];
|
|
258
|
+
}
|
|
259
|
+
result.isPreview = element.isPreview;
|
|
260
|
+
if (!result.isPreview) {
|
|
261
|
+
result.isPreview = false;
|
|
262
|
+
}
|
|
263
|
+
if (element.deprecated) {
|
|
264
|
+
result.isDeprecated = true;
|
|
265
|
+
result.customDeprecatedMessage = element.deprecated.content;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
result.isDeprecated = false;
|
|
269
|
+
}
|
|
270
|
+
if (element.syntax) {
|
|
271
|
+
result.syntax = {};
|
|
272
|
+
const syntax = element.syntax;
|
|
273
|
+
result.syntax.content = syntax.content;
|
|
274
|
+
if (syntax.parameters && syntax.parameters.length > 0) {
|
|
275
|
+
(_a = syntax.parameters) === null || _a === void 0 ? void 0 : _a.forEach((it) => {
|
|
276
|
+
delete it.optional;
|
|
277
|
+
delete it.defaultValue;
|
|
278
|
+
});
|
|
279
|
+
result.syntax.parameters = syntax.parameters.map((it) => {
|
|
280
|
+
return {
|
|
281
|
+
...it,
|
|
282
|
+
id: it.id,
|
|
283
|
+
type: convertSelfTypeToXref(escapeMarkdown(it.type[0]), transfomredClass)
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
if (syntax.return) {
|
|
288
|
+
result.syntax.return = {
|
|
289
|
+
...syntax.return,
|
|
290
|
+
type: convertSelfTypeToXref(escapeMarkdown(syntax.return.type[0]), transfomredClass)
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return result;
|
|
295
|
+
}
|
|
296
|
+
function escapeMarkdown(name) {
|
|
297
|
+
// eg: [key: string]: string
|
|
298
|
+
const markdownLinkRegEx = /^\s*(\[.+\]):(.+)/g;
|
|
299
|
+
return name.replace(markdownLinkRegEx, `$1\\:$2`);
|
|
300
|
+
}
|
|
301
|
+
function convertSelfTypeToXref(name, transfomredClass) {
|
|
302
|
+
var _a, _b, _c;
|
|
303
|
+
let result = name;
|
|
304
|
+
// if complex type, need to get real type from references
|
|
305
|
+
if (result.endsWith(':complex')) {
|
|
306
|
+
const specs = (_b = (_a = transfomredClass.references) === null || _a === void 0 ? void 0 : _a.find((item) => {
|
|
307
|
+
return item.uid === name;
|
|
308
|
+
})) === null || _b === void 0 ? void 0 : _b['spec.typeScript'];
|
|
309
|
+
if (specs && specs.length > 0) {
|
|
310
|
+
result = '';
|
|
311
|
+
for (const spec of specs) {
|
|
312
|
+
// start with ! will be node base type
|
|
313
|
+
if (spec.uid && !spec.uid.startsWith('!')) {
|
|
314
|
+
result += spec.uid;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
result += spec.name;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else if (result.startsWith('!')) {
|
|
323
|
+
// uid: '!Object:interface'
|
|
324
|
+
// name: Object
|
|
325
|
+
// start with !, not complex type, use reference name directly
|
|
326
|
+
const ref = (_c = transfomredClass.references) === null || _c === void 0 ? void 0 : _c.find((item) => {
|
|
327
|
+
return item.uid === name;
|
|
328
|
+
});
|
|
329
|
+
if (ref && ref.name) {
|
|
330
|
+
result = ref.name;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// parse < >
|
|
334
|
+
result = result.replace(/</g, '<').replace(/>/g, '>');
|
|
335
|
+
const uidRegEx = /(@?[\w\d\-/!~\.]+\:[\w\d\-\(/]+)/g;
|
|
336
|
+
return result.replace(uidRegEx, `<xref uid="$1" />`);
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=ToSdpConvertHelper.js.map
|