Skip to content

Commit e0aba76

Browse files
authored
Implement @webonly tag to exclude items from Node docs (#1679)
- Use built-in Typescript AST tools to generate a temporary abridged copy of `index.d.ts` as a source for generating Node documentation. - `@webonly` tag used to indicate which sections to omit. - Custom Typedoc theme updated to not display `@webonly` as a tag section in doc output. - Rearrange signature/description ordering of overloaded methods.
1 parent 077b88b commit e0aba76

File tree

7 files changed

+129
-7
lines changed

7 files changed

+129
-7
lines changed

packages/firebase/index.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ declare namespace firebase {
362362
* console.</dd>
363363
* </dl>
364364
*
365+
* @webonly
366+
*
365367
* @example
366368
* ```javascript
367369
* // Creates the provider object.
@@ -577,6 +579,8 @@ declare namespace firebase {
577579
* console.</dd>
578580
* </dl>
579581
*
582+
* @webonly
583+
*
580584
* @example
581585
* ```javascript
582586
* // Creates the provider object.
@@ -625,6 +629,8 @@ declare namespace firebase {
625629
* console.</dd>
626630
* </dl>
627631
*
632+
* @webonly
633+
*
628634
* @param provider The provider to authenticate.
629635
* The provider has to be an OAuth provider. Non-OAuth providers like {@link
630636
* firebase.auth.EmailAuthProvider} will throw an error.
@@ -992,6 +998,8 @@ declare namespace firebase {
992998
* generating notifications if the push message payload has a `notification`
993999
* parameter.
9941000
*
1001+
* @webonly
1002+
*
9951003
* @example
9961004
* ```javascript
9971005
* // Get the Messaging service for the default app
@@ -1020,6 +1028,8 @@ declare namespace firebase {
10201028
* {@link firebase.storage.Storage `Storage`} service associated with a
10211029
* specific app.
10221030
*
1031+
* @webonly
1032+
*
10231033
* @example
10241034
* ```javascript
10251035
* // Get the Storage service for the default app
@@ -1039,6 +1049,9 @@ declare namespace firebase {
10391049

10401050
function firestore(app?: firebase.app.App): firebase.firestore.Firestore;
10411051

1052+
/**
1053+
* @webonly
1054+
*/
10421055
function functions(app?: firebase.app.App): firebase.functions.Functions;
10431056
}
10441057

@@ -1095,6 +1108,8 @@ declare namespace firebase.app {
10951108
* Gets the {@link firebase.messaging.Messaging `Messaging`} service for the
10961109
* current app.
10971110
*
1111+
* @webonly
1112+
*
10981113
* @example
10991114
* ```javascript
11001115
* var messaging = app.messaging();
@@ -1139,6 +1154,8 @@ declare namespace firebase.app {
11391154
* Gets the {@link firebase.storage.Storage `Storage`} service for the current
11401155
* app, optionally initialized with a custom storage bucket.
11411156
*
1157+
* @webonly
1158+
*
11421159
* @example
11431160
* ```javascript
11441161
* var storage = app.storage();
@@ -1156,10 +1173,16 @@ declare namespace firebase.app {
11561173
*/
11571174
storage(url?: string): firebase.storage.Storage;
11581175
firestore(): firebase.firestore.Firestore;
1176+
/**
1177+
* @webonly
1178+
*/
11591179
functions(region?: string): firebase.functions.Functions;
11601180
}
11611181
}
11621182

1183+
/**
1184+
* @webonly
1185+
*/
11631186
declare namespace firebase.functions {
11641187
/**
11651188
* An HttpsCallableResult wraps a single result from a function call.
@@ -1702,6 +1725,8 @@ declare namespace firebase.auth {
17021725
* Firebase console.</dd>
17031726
* </dl>
17041727
*
1728+
* @webonly
1729+
*
17051730
* @example
17061731
* ```javascript
17071732
* // First, we perform the signInWithRedirect.
@@ -2508,6 +2533,8 @@ declare namespace firebase.auth {
25082533
* console.</dd>
25092534
* </dl>
25102535
*
2536+
* @webonly
2537+
*
25112538
* @example
25122539
* ```javascript
25132540
* // Creates the provider object.
@@ -2569,6 +2596,8 @@ declare namespace firebase.auth {
25692596
* console.</dd>
25702597
* </dl>
25712598
*
2599+
* @webonly
2600+
*
25722601
* @param provider The provider to authenticate.
25732602
* The provider has to be an OAuth provider. Non-OAuth providers like {@link
25742603
* firebase.auth.EmailAuthProvider} will throw an error.
@@ -3359,6 +3388,9 @@ declare namespace firebase.auth {
33593388
/**
33603389
* An {@link https://www.google.com/recaptcha/ reCAPTCHA}-based application
33613390
* verifier.
3391+
*
3392+
* @webonly
3393+
*
33623394
* @param container The reCAPTCHA container parameter. This
33633395
* has different meaning depending on whether the reCAPTCHA is hidden or
33643396
* visible. For a visible reCAPTCHA the container must be empty. If a string
@@ -3376,6 +3408,7 @@ declare namespace firebase.auth {
33763408
*/
33773409
class RecaptchaVerifier extends RecaptchaVerifier_Instance {}
33783410
/**
3411+
* @webonly
33793412
* @hidden
33803413
*/
33813414
class RecaptchaVerifier_Instance
@@ -5166,6 +5199,9 @@ declare namespace firebase.database.ServerValue {
51665199
var TIMESTAMP: Object;
51675200
}
51685201

5202+
/**
5203+
* @webonly
5204+
*/
51695205
declare namespace firebase.messaging {
51705206
/**
51715207
* The Firebase Messaging service interface.
@@ -5270,6 +5306,9 @@ declare namespace firebase.messaging {
52705306
function isSupported(): boolean;
52715307
}
52725308

5309+
/**
5310+
* @webonly
5311+
*/
52735312
declare namespace firebase.storage {
52745313
/**
52755314
* The full set of object metadata, including read-only properties.

scripts/docgen/content-sources/node/toc.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ toc:
5050
path: /docs/reference/node/firebase.auth.PhoneAuthProvider
5151
- title: "SAMLAuthProvider"
5252
path: /docs/reference/node/firebase.auth.SAMLAuthProvider
53-
- title: "RecaptchaVerifier"
54-
path: /docs/reference/node/firebase.auth.RecaptchaVerifier
5553
- title: "UserMetadata"
5654
path: /docs/reference/node/firebase.auth.UserMetadata
5755
- title: "User"

scripts/docgen/generate-docs.js

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const yargs = require('yargs');
2020
const fs = require('mz/fs');
2121
const path = require('path');
2222
const yaml = require('js-yaml');
23+
const typescript = require('typescript');
2324

2425
const repoPath = path.resolve(`${__dirname}/../..`);
2526

@@ -41,6 +42,7 @@ const { api: apiType, source: sourceFile } = yargs
4142
const docPath = path.resolve(`${__dirname}/html/${apiType}`);
4243
const contentPath = path.resolve(`${__dirname}/content-sources/${apiType}`);
4344
const tempHomePath = path.resolve(`${contentPath}/HOME_TEMP.md`);
45+
const tempNodeSourcePath = path.resolve(`${__dirname}/index.node.d.ts`);
4446
const devsitePath = `/docs/reference/${apiType}/`;
4547

4648
/**
@@ -58,7 +60,8 @@ function stripPath(path) {
5860
* Additional config options come from ./typedoc.js
5961
*/
6062
function runTypedoc() {
61-
const command = `${repoPath}/node_modules/.bin/typedoc ${sourceFile} \
63+
const typeSource = apiType === 'node' ? tempNodeSourcePath : sourceFile;
64+
const command = `${repoPath}/node_modules/.bin/typedoc ${typeSource} \
6265
--out ${docPath} \
6366
--readme ${tempHomePath} \
6467
--options ${__dirname}/typedoc.js \
@@ -111,7 +114,7 @@ function generateTempHomeMdFile(tocRaw, homeRaw) {
111114
const { toc } = yaml.safeLoad(tocRaw);
112115
let tocPageLines = [homeRaw, '# API Reference'];
113116
toc.forEach(group => {
114-
tocPageLines.push(`\n## [${group.title}](${stripPath(group.path)})`);
117+
tocPageLines.push(`\n## [${group.title}](${stripPath(group.path)}.html)`);
115118
group.section.forEach(item => {
116119
tocPageLines.push(`- [${item.title}](${stripPath(item.path)}.html)`);
117120
});
@@ -240,6 +243,55 @@ function fixAllLinks(htmlFiles) {
240243
return Promise.all(writePromises);
241244
}
242245

246+
/**
247+
* Generate an temporary abridged version of index.d.ts used to create
248+
* Node docs.
249+
*/
250+
async function generateNodeSource() {
251+
const sourceText = await fs.readFile(sourceFile, 'utf8');
252+
253+
// Parse index.d.ts. A dummy filename is required but it doesn't create a
254+
// file.
255+
let typescriptSourceFile = typescript.createSourceFile(
256+
'temp.d.ts',
257+
sourceText,
258+
typescript.ScriptTarget.ES2015,
259+
/*setParentNodes */ false
260+
);
261+
262+
/**
263+
* Typescript transformer function. Removes nodes tagged with @webonly.
264+
*/
265+
const removeWebOnlyNodes = context => rootNode => {
266+
function visit(node) {
267+
if (
268+
node.jsDoc &&
269+
node.jsDoc.some(
270+
item =>
271+
item.tags &&
272+
item.tags.some(tag => tag.tagName.escapedText === 'webonly')
273+
)
274+
) {
275+
return null;
276+
}
277+
return typescript.visitEachChild(node, visit, context);
278+
}
279+
return typescript.visitNode(rootNode, visit);
280+
};
281+
282+
// Use above transformer on source AST to remove nodes tagged with @webonly.
283+
const result = typescript.transform(typescriptSourceFile, [
284+
removeWebOnlyNodes
285+
]);
286+
287+
// Convert transformed AST to text and write to file.
288+
const printer = typescript.createPrinter();
289+
return fs.writeFile(
290+
tempNodeSourcePath,
291+
printer.printFile(result.transformed[0])
292+
);
293+
}
294+
243295
/**
244296
* Main document generation process.
245297
*
@@ -262,13 +314,22 @@ Promise.all([
262314
tocText = tocRaw;
263315
return generateTempHomeMdFile(tocRaw, homeRaw);
264316
})
317+
.then(() => {
318+
if (apiType === 'node') {
319+
return generateNodeSource();
320+
}
321+
})
265322
// Run main Typedoc process (uses index.d.ts and generated temp file above).
266323
.then(runTypedoc)
267-
.then(output => {
324+
.then(async output => {
268325
// Typedoc output.
269326
console.log(output.stdout);
270327
// Clean up temp home markdown file. (Nothing needs to wait for this.)
271328
fs.unlink(tempHomePath);
329+
// Clean up temp node index.d.ts file if it exists.
330+
if (await fs.exists(tempNodeSourcePath)) {
331+
fs.unlink(tempNodeSourcePath);
332+
}
272333
// Devsite doesn't like css.map files.
273334
return fs.unlink(`${docPath}/assets/css/main.css.map`);
274335
})

scripts/docgen/theme/assets/css/firebase.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,17 @@
3737

3838
.firebase-docs .tsd-breadcrumb .model-name {
3939
color: #333;
40+
}
41+
42+
.firebase-docs .tsd-signature {
43+
border-bottom: 1px solid #eee;
44+
}
45+
46+
.firebase-docs .tsd-description {
47+
display: block;
48+
padding-left: 20px;
49+
}
50+
51+
.firebase-docs li.tsd-description:not(:last-child) {
52+
margin-bottom: 20px;
4053
}

scripts/docgen/theme/assets/css/main.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,11 @@ footer .tsd-legend { display: inline-block; width: 25%; padding: 0; font-size: 1
486486
.tsd-signature-type { font-style: italic; font-weight: normal; }
487487

488488
.tsd-signatures { padding: 0; margin: 0 0 1em 0; border: 1px solid #eee; }
489-
.tsd-signatures .tsd-signature { margin: 0; border-width: 1px 0 0 0; transition: background-color 0.1s; }
489+
.tsd-signatures .tsd-signature { margin: 0; border-width: 1px 0; transition: background-color 0.1s; }
490490
.tsd-signatures .tsd-signature:first-child { border-top-width: 0; }
491491
.tsd-signatures .tsd-signature.current { background-color: #eee; }
492492
.tsd-signatures.active > .tsd-signature { cursor: pointer; }
493-
.tsd-panel > .tsd-signatures { margin-left: -20px; margin-right: -20px; border-width: 1px 0; }
493+
.tsd-panel > .tsd-signatures { margin-left: -20px; margin-right: -20px; border-width: 1px 0; padding-bottom: 5px }
494494
.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon { padding-left: 40px; }
495495
.tsd-panel > a.anchor + .tsd-signatures { border-top-width: 0; margin-top: -20px; }
496496

scripts/docgen/theme/partials/comment.hbs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
{{#if tags}}
1313
<dl class="tsd-comment-tags">
1414
{{#each tags}}
15+
{{#ifCond tagName '==' "webonly"}}
16+
{{else}}
1517
<dt class="tag-{{tagName}}">{{tagName}}</dt>
1618
<dd class="tag-body-{{tagName}}">{{#markdown}}{{{text}}}{{/markdown}}</dd>
19+
{{/ifCond}}
1720
{{/each}}
1821
</dl>
1922
{{/if}}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<ul class="tsd-signatures {{cssClasses}}">
2+
{{#each signatures}}
3+
<li class="tsd-signature tsd-kind-icon">{{> member.signature.title }}</li>
4+
<li class="tsd-description">
5+
{{> member.signature.body }}
6+
</li>
7+
{{/each}}
8+
</ul>

0 commit comments

Comments
 (0)