Skip to content

Commit 19ff1ed

Browse files
author
Nick Pape
committed
Merge branch 'master' into nickpape/add-file-system
2 parents 138d91d + 93e70d3 commit 19ff1ed

File tree

8 files changed

+159
-27
lines changed

8 files changed

+159
-27
lines changed

apps/api-documenter/CHANGELOG.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
{
22
"name": "@microsoft/api-documenter",
33
"entries": [
4+
{
5+
"version": "1.4.0",
6+
"tag": "@microsoft/api-documenter_v1.4.0",
7+
"date": "Tue, 26 Jun 2018 23:54:17 GMT",
8+
"comments": {
9+
"minor": [
10+
{
11+
"comment": "The YAML target now automatically hyperlinks type references, but only if the type name is simple and not ambiguous"
12+
}
13+
]
14+
}
15+
},
16+
{
17+
"version": "1.3.1",
18+
"tag": "@microsoft/api-documenter_v1.3.1",
19+
"date": "Tue, 26 Jun 2018 16:04:59 GMT",
20+
"comments": {
21+
"patch": [
22+
{
23+
"comment": "Improve OfficeYamlDocumenter to replace escaped function arrows in code lines with =>"
24+
}
25+
]
26+
}
27+
},
428
{
529
"version": "1.3.0",
630
"tag": "@microsoft/api-documenter_v1.3.0",

apps/api-documenter/CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
# Change Log - @microsoft/api-documenter
22

3-
This log was last generated on Sat, 23 Jun 2018 02:21:20 GMT and should not be manually modified.
3+
This log was last generated on Tue, 26 Jun 2018 23:54:17 GMT and should not be manually modified.
4+
5+
## 1.4.0
6+
Tue, 26 Jun 2018 23:54:17 GMT
7+
8+
### Minor changes
9+
10+
- The YAML target now automatically hyperlinks type references, but only if the type name is simple and not ambiguous
11+
12+
## 1.3.1
13+
Tue, 26 Jun 2018 16:04:59 GMT
14+
15+
### Patches
16+
17+
- Improve OfficeYamlDocumenter to replace escaped function arrows in code lines with =>
418

519
## 1.3.0
620
Sat, 23 Jun 2018 02:21:20 GMT

apps/api-documenter/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@microsoft/api-documenter",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "Read JSON files from api-extractor, generate documentation pages",
55
"repository": {
66
"type": "git",

apps/api-documenter/src/cli/BaseAction.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ export abstract class BaseAction extends CommandLineAction {
5757
}
5858
}
5959

60-
docItemSet.calculateReferences();
61-
6260
return docItemSet;
6361
}
6462
}

apps/api-documenter/src/utils/DocItemSet.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,16 @@ export class DocItem {
157157
}
158158
return undefined;
159159
}
160+
161+
/**
162+
* Visits this DocItem and every child DocItem in a preorder traversal.
163+
*/
164+
public forEach(callback: (docItem: DocItem) => void): void {
165+
callback(this);
166+
for (const child of this.children) {
167+
child.forEach(callback);
168+
}
169+
}
160170
}
161171

162172
/**
@@ -186,29 +196,15 @@ export interface IDocItemSetResolveResult {
186196
export class DocItemSet {
187197
public readonly docPackagesByName: Map<string, DocItem> = new Map<string, DocItem>();
188198
public readonly docPackages: DocItem[] = [];
189-
private _calculated: boolean = false;
190199

191200
public loadApiJsonFile(apiJsonFilename: string): void {
192-
if (this._calculated) {
193-
throw new Error('calculateReferences() was already called');
194-
}
195-
196201
const apiPackage: IApiPackage = ApiJsonFile.loadFromFile(apiJsonFilename);
197202

198203
const docItem: DocItem = new DocItem(apiPackage, apiPackage.name, this, undefined);
199204
this.docPackagesByName.set(apiPackage.name, docItem);
200205
this.docPackages.push(docItem);
201206
}
202207

203-
public calculateReferences(): void {
204-
if (this._calculated) {
205-
return;
206-
}
207-
for (const docPackage of this.docPackages) {
208-
this._calculateReferences(docPackage);
209-
}
210-
}
211-
212208
/**
213209
* Attempts to find the DocItem described by an IApiItemReference. If no matching item is
214210
* found, then undefined is returned.
@@ -249,11 +245,12 @@ export class DocItemSet {
249245
return result;
250246
}
251247

252-
private _calculateReferences(docItem: DocItem): void {
253-
// (Calculate base classes and child classes)
254-
255-
for (const child of docItem.children) {
256-
this._calculateReferences(child);
248+
/**
249+
* Visits every DocItem in the tree.
250+
*/
251+
public forEach(callback: (docItem: DocItem) => void): void {
252+
for (const docPackage of this.docPackages) {
253+
docPackage.forEach(callback);
257254
}
258255
}
259256
}

apps/api-documenter/src/yaml/OfficeYamlDocumenter.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export class OfficeYamlDocumenter extends YamlDocumenter {
9696
yamlItem.remarks = this._fixupApiSet(yamlItem.remarks, yamlItem.uid);
9797
yamlItem.remarks = this._fixBoldAndItalics(yamlItem.remarks);
9898
yamlItem.remarks = this._fixCodeTicks(yamlItem.remarks);
99+
yamlItem.remarks = this._fixCodeArrows(yamlItem.remarks);
99100
}
100101
if (yamlItem.syntax && yamlItem.syntax.parameters) {
101102
yamlItem.syntax.parameters.forEach(part => {
@@ -135,4 +136,8 @@ export class OfficeYamlDocumenter extends YamlDocumenter {
135136
private _fixCodeTicks(text: string): string {
136137
return Text.replaceAll(text, '\\`', '`');
137138
}
139+
140+
private _fixCodeArrows(text: string): string {
141+
return Text.replaceAll(text, '=&gt;', '=>');
142+
}
138143
}

apps/api-documenter/src/yaml/YamlDocumenter.ts

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,21 @@ const yamlApiSchema: JsonSchema = JsonSchema.fromFile(path.join(__dirname, 'type
4545
*/
4646
export class YamlDocumenter {
4747
private _docItemSet: DocItemSet;
48+
49+
// This is used by the _linkToUidIfPossible() workaround.
50+
// It stores a mapping from type name (e.g. "MyClass") to the corresponding DocItem.
51+
// If the mapping would be ambiguous (e.g. "MyClass" is defined by multiple packages)
52+
// then it is excluded from the mapping. Also excluded are DocItems (such as package
53+
// and function) which are not typically used as a data type.
54+
private _docItemsByTypeName: Map<string, DocItem>;
55+
4856
private _outputFolder: string;
4957

5058
public constructor(docItemSet: DocItemSet) {
5159
this._docItemSet = docItemSet;
60+
this._docItemsByTypeName = new Map<string, DocItem>();
61+
62+
this._initDocItemsByTypeName();
5263
}
5364

5465
public generateFiles(outputFolder: string): void { // virtual
@@ -335,7 +346,7 @@ export class YamlDocumenter {
335346
.replace(/^\s*-\s+/, ''); // temporary workaround for people who mistakenly add a hyphen, e.g. "@returns - blah"
336347

337348
syntax.return = {
338-
type: [ apiMethod.returnValue.type ],
349+
type: [ this._linkToUidIfPossible(apiMethod.returnValue.type) ],
339350
description: returnDescription
340351
};
341352
}
@@ -347,7 +358,7 @@ export class YamlDocumenter {
347358
{
348359
id: parameterName,
349360
description: this._renderMarkdown(apiParameter.description, docItem),
350-
type: [ apiParameter.type || '' ]
361+
type: [ this._linkToUidIfPossible(apiParameter.type || '') ]
351362
} as IYamlParameter
352363
);
353364
}
@@ -369,7 +380,7 @@ export class YamlDocumenter {
369380

370381
if (apiProperty.type) {
371382
syntax.return = {
372-
type: [ apiProperty.type ]
383+
type: [ this._linkToUidIfPossible(apiProperty.type) ]
373384
};
374385
}
375386
}
@@ -454,6 +465,89 @@ export class YamlDocumenter {
454465
return result;
455466
}
456467

468+
/**
469+
* Initialize the _docItemsByTypeName() data structure.
470+
*/
471+
private _initDocItemsByTypeName(): void {
472+
// Collect the _docItemsByTypeName table
473+
const ambiguousNames: Set<string> = new Set<string>();
474+
475+
this._docItemSet.forEach((docItem: DocItem) => {
476+
switch (docItem.kind) {
477+
case DocItemKind.Class:
478+
case DocItemKind.Enum:
479+
case DocItemKind.Interface:
480+
// Attempt to register both the fully qualified name and the short name
481+
const namesForType: string[] = [docItem.name];
482+
483+
// Note that nameWithDot cannot conflict with docItem.name (because docItem.name
484+
// cannot contain a dot)
485+
const nameWithDot: string | undefined = this._getTypeNameWithDot(docItem);
486+
if (nameWithDot) {
487+
namesForType.push(nameWithDot);
488+
}
489+
490+
// Register all names
491+
for (const typeName of namesForType) {
492+
if (ambiguousNames.has(typeName)) {
493+
break;
494+
}
495+
496+
if (this._docItemsByTypeName.has(typeName)) {
497+
// We saw this name before, so it's an ambiguous match
498+
ambiguousNames.add(typeName);
499+
break;
500+
}
501+
502+
this._docItemsByTypeName.set(typeName, docItem);
503+
}
504+
505+
break;
506+
}
507+
});
508+
509+
// Remove the ambiguous matches
510+
for (const ambiguousName of ambiguousNames) {
511+
this._docItemsByTypeName.delete(ambiguousName);
512+
}
513+
}
514+
515+
/**
516+
* This is a temporary workaround to enable limited autolinking of API item types
517+
* until the YAML file format is enhanced to support general hyperlinks.
518+
* @remarks
519+
* In the current version, fields such as IApiProperty.type allow either:
520+
* (1) a UID identifier such as "node-core-library.JsonFile" which will be rendered
521+
* as a hyperlink to that type name, or (2) a block of freeform text that must not
522+
* contain any Markdown links. The _substituteUidForSimpleType() function assumes
523+
* it is given #2 but substitutes #1 if the name can be matched to a DocItem.
524+
*/
525+
private _linkToUidIfPossible(typeName: string): string {
526+
// Note that typeName might be a _getTypeNameWithDot() name or it might be a simple class name
527+
const docItem: DocItem | undefined = this._docItemsByTypeName.get(typeName.trim());
528+
if (docItem) {
529+
// Substitute the UID
530+
return this._getUid(docItem);
531+
}
532+
return typeName;
533+
}
534+
535+
/**
536+
* If the docItem represents a scoped name such as "my-library:MyNamespace.MyClass",
537+
* this returns a string such as "MyNamespace.MyClass". If the result would not
538+
* have at least one dot in it, then undefined is returned.
539+
*/
540+
private _getTypeNameWithDot(docItem: DocItem): string | undefined {
541+
const hierarchy: DocItem[] = docItem.getHierarchy();
542+
if (hierarchy.length > 0 && hierarchy[0].kind === DocItemKind.Package) {
543+
hierarchy.shift(); // ignore the package qualifier
544+
}
545+
if (hierarchy.length < 1) {
546+
return undefined;
547+
}
548+
return hierarchy.map(x => x.name).join('.');
549+
}
550+
457551
private _getYamlItemName(docItem: DocItem): string {
458552
if (docItem.parent && docItem.parent.kind === DocItemKind.Namespace) {
459553
// For members a namespace, show the full name excluding the package part:

build-tests/api-extractor-test-05/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
"dependencies": {
1515
"@microsoft/api-extractor": "5.9.0",
16-
"@microsoft/api-documenter": "1.3.0",
16+
"@microsoft/api-documenter": "1.4.0",
1717
"@types/jest": "21.1.10",
1818
"@types/node": "8.5.8",
1919
"fs-extra": "~5.0.0",

0 commit comments

Comments
 (0)