diff --git a/.gitignore b/.gitignore index d345a2f7a..ba3cdeec5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .tmp .vscode/ coverage +docgen/html firebase-functions-*.tgz integration_test/.firebaserc integration_test/*.log diff --git a/docgen/content-sources/HOME.md b/docgen/content-sources/HOME.md new file mode 100644 index 000000000..c89df0a57 --- /dev/null +++ b/docgen/content-sources/HOME.md @@ -0,0 +1,3 @@ +# Firebase Functions SDK Reference + +Functions SDK!!! diff --git a/docgen/content-sources/toc.yaml b/docgen/content-sources/toc.yaml new file mode 100644 index 000000000..c2766e430 --- /dev/null +++ b/docgen/content-sources/toc.yaml @@ -0,0 +1,114 @@ +toc: + - title: 'functions' + path: /docs/reference/functions/cloud_functions_.html + section: + - title: 'CloudFunction' + path: /docs/reference/functions/cloud_functions_.html#cloudfunction + - title: 'HttpsFunction' + path: /docs/reference/functions/cloud_functions_.html#httpsfunction + - title: 'EventContext' + path: /docs/reference/functions/cloud_functions_.eventcontext.html + - title: 'FunctionBuilder' + path: /docs/reference/functions/function_builder_.functionbuilder.html + - title: 'Change' + path: /docs/reference/functions/cloud_functions_.change.html + + - title: 'functions.config' + path: /docs/reference/functions/config_.html + section: + - title: 'Config' + path: /docs/reference/functions/config_.config.html + + - title: 'functions.analytics' + path: /docs/reference/functions/providers_analytics_.html + section: + - title: 'AnalyticsEvent' + path: /docs/reference/functions/providers_analytics_.analyticsevent.html + - title: 'AnalyticsEventBuilder' + path: /docs/reference/functions/providers_analytics_.analyticseventbuilder.html + - title: 'AppInfo' + path: /docs/reference/functions/providers_analytics_.appinfo.html + - title: 'DeviceInfo' + path: /docs/reference/functions/providers_analytics_.deviceinfo.html + - title: 'ExportBundleInfo' + path: /docs/reference/functions/providers_analytics_.exportbundleinfo.html + - title: 'GeoInfo' + path: /docs/reference/functions/providers_analytics_.geoinfo.html + - title: 'UserDimensions' + path: /docs/reference/functions/providers_analytics_.userdimensions.html + - title: 'UserPropertyValue' + path: /docs/reference/functions/providers_analytics_.userpropertyvalue.html + + - title: 'functions.auth' + path: /docs/reference/functions/providers_auth_.html + section: + - title: 'UserBuilder' + path: /docs/reference/functions/providers_auth_.userbuilder.html + - title: 'UserInfo' + path: /docs/reference/functions/providers_auth_.html#userinfo + - title: 'UserRecordMetadata' + path: /docs/reference/functions/providers_auth_.userrecordmetadata.html + - title: 'UserRecord' + path: /docs/reference/functions/providers_auth_.html#userrecord + + - title: 'functions.crashlytics' + path: /docs/reference/functions/providers_crashlytics_.html + section: + - title: 'Issue' + path: /docs/reference/functions/providers_crashlytics_.issue.html + - title: 'IssueBuilder' + path: /docs/reference/functions/providers_crashlytics_.issuebuilder.html + - title: 'AppInfo' + path: /docs/reference/functions/providers_crashlytics_.appinfo.html + - title: 'VelocityAlert' + path: /docs/reference/functions/providers_crashlytics_.velocityalert.html + + - title: 'functions.firestore' + path: /docs/reference/functions/providers_firestore_.html + section: + - title: 'DocumentBuilder' + path: /docs/reference/functions/providers_firestore_.documentbuilder.html + - title: 'DocumentSnapshot' + path: /docs/reference/functions/providers_firestore_.html#documentsnapshot + + - title: 'functions.database' + path: /docs/reference/functions/providers_database_.html + section: + - title: 'DataSnapshot' + path: /docs/reference/functions/providers_database_.datasnapshot.html + - title: 'RefBuilder' + path: /docs/reference/functions/providers_database_.refbuilder.html + - title: 'InstanceBuilder' + path: /docs/reference/functions/providers_database_.instancebuilder.html + + - title: 'functions.https' + path: /docs/reference/functions/providers_https_.html + section: + - title: 'HttpsError' + path: /docs/reference/functions/providers_https_.httpserror.html + + - title: 'functions.pubsub' + path: /docs/reference/functions/providers_pubsub_.html + section: + - title: 'Message' + path: /docs/reference/functions/providers_pubsub_.message.html + - title: 'TopicBuilder' + path: /docs/reference/functions/providers_pubsub_.topicbuilder.html + + - title: 'functions.remoteconfig' + path: /docs/reference/functions/providers_remoteconfig_.html + section: + - title: 'RemoteConfigUser' + path: /docs/reference/functions/providers_remoteconfig_.remoteconfiguser.html + - title: 'TemplateVersion' + path: /docs/reference/functions/providers_remoteconfig_.templateversion.html + + - title: 'functions.storage' + path: /docs/reference/functions/providers_storage_.html + section: + - title: 'BucketBuilder' + path: /docs/reference/functions/providers_storage_.bucketbuilder.html + - title: 'ObjectBuilder' + path: /docs/reference/functions/providers_storage_.objectbuilder.html + - title: 'ObjectMetadata' + path: /docs/reference/functions/providers_storage_.objectmetadata.html diff --git a/docgen/generate-docs.js b/docgen/generate-docs.js new file mode 100644 index 000000000..299250e64 --- /dev/null +++ b/docgen/generate-docs.js @@ -0,0 +1,339 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const { exec } = require('child-process-promise'); +const fs = require('mz/fs'); +const path = require('path'); +const yargs = require('yargs'); +const yaml = require('js-yaml'); +const _ = require('lodash'); + +const repoPath = path.resolve(`${__dirname}/..`); + +// Command-line options. +const { source: sourceFile } = yargs + .option('source', { + default: `${repoPath}/src`, + describe: 'Typescript source file(s)', + type: 'string' + }) + .version(false) + .help().argv; + +const docPath = path.resolve(`${__dirname}/html`); +const contentPath = path.resolve(`${__dirname}/content-sources`); +const tempHomePath = path.resolve(`${contentPath}/HOME_TEMP.md`); +const devsitePath = `/docs/reference/functions/`; + +/** + * Strips path prefix and returns only filename. + * @param {string} path + */ +function stripPath(path) { + const parts = path.split('/'); + return parts[parts.length - 1]; +} + +/** + * Runs Typedoc command. + * + * Additional config options come from ./typedoc.js + */ +function runTypedoc() { + const command = `${repoPath}/node_modules/.bin/typedoc ${sourceFile} \ + --out ${docPath} \ + --readme ${tempHomePath} \ + --options ${__dirname}/typedoc.js \ + --theme ${__dirname}/theme`; + + console.log('Running command:\n', command); + return exec(command); +} + +/** + * Moves files from subdir to root. + * @param {string} subdir Subdir to move files out of. + */ +function moveFilesToRoot(subdir) { + return exec(`mv ${docPath}/${subdir}/* ${docPath}`) + .then(() => { + exec(`rmdir ${docPath}/${subdir}`); + }) + .catch(e => console.error(e)); +} + +/** + * Renames files to remove the leading underscores. + * We need to do this because devsite hides these files. + * Example: + * _cloud_functions_.resource.html => cloud_functions_.resource.html + */ +function renameFiles() { + return fs.readdir(docPath).then(files => { + console.log(files); + files.forEach(file => { + let newFileName = file; + if (_.startsWith(file, "_") && _.endsWith(file, "html")) { + newFileName = _.trimStart(file, "_"); + fs.rename(`${docPath}/${file}`, `${docPath}/${newFileName}`, (err) => { + if (err) console.log(err) + }); + } + }) + }) +} + +/** + * Reformat links to match flat structure. + * @param {string} file File to fix links in. + */ +function fixLinks(file) { + return fs.readFile(file, 'utf8').then(data => { + const flattenedLinks = data + .replace(/\.\.\//g, '') + .replace(/(modules|interfaces|classes)\//g, '') + .replace(/\"_/g, '"'); + let caseFixedLinks = flattenedLinks; + for (const lower in lowerToUpperLookup) { + const re = new RegExp(lower, 'g'); + caseFixedLinks = caseFixedLinks.replace(re, lowerToUpperLookup[lower]); + } + return fs.writeFile(file, caseFixedLinks); + }); +} + +let tocText = ''; + +/** + * Generates temporary markdown file that will be sourced by Typedoc to + * create index.html. + * + * @param {string} tocRaw + * @param {string} homeRaw + */ +function generateTempHomeMdFile(tocRaw, homeRaw) { + const { toc } = yaml.safeLoad(tocRaw); + let tocPageLines = [homeRaw, '# API Reference']; + toc.forEach(group => { + tocPageLines.push(`\n## [${group.title}](${stripPath(group.path)})`); + const section = group.section || []; + section.forEach(item => { + tocPageLines.push(`- [${item.title}](${stripPath(item.path)})`); + }); + }); + return fs.writeFile(tempHomePath, tocPageLines.join('\n')); +} + +/** + * Mapping between lowercase file name and correctly cased name. + * Used to update links when filenames are capitalized. + */ +const lowerToUpperLookup = {}; + +/** + * Checks to see if any files listed in toc.yaml were not generated. + * If files exist, fixes filename case to match toc.yaml version. + */ +function checkForMissingFilesAndFixFilenameCase() { + // Get filenames from toc.yaml. + const filenames = tocText + .split('\n') + .filter(line => line.includes('path:')) + .map(line => line.split(devsitePath)[1]); + // Logs warning to console if a file from TOC is not found. + // console.log(filenames); + const fileCheckPromises = filenames.map(filename => { + // Warns if file does not exist, fixes filename case if it does. + // Preferred filename for devsite should be capitalized and taken from + // toc.yaml. + const tocFilePath = `${docPath}/${filename}`; + // Generated filename from Typedoc will be lowercase. + const generatedFilePath = `${docPath}/${filename.toLowerCase()}`; + return fs.exists(generatedFilePath).then(exists => { + if (exists) { + // Store in a lookup table for link fixing. + lowerToUpperLookup[ + `${filename.toLowerCase()}` + ] = `${filename}`; + return fs.rename(generatedFilePath, tocFilePath); + } else { + console.warn( + `Missing file: ${filename} requested ` + + `in toc.yaml but not found in ${docPath}` + ); + } + }); + }); + return Promise.all(fileCheckPromises).then(() => filenames); +} + +/** + * Gets a list of html files in generated dir and checks if any are not + * found in toc.yaml. + * Option to remove the file if not found (used for node docs). + * + * @param {Array} filenamesFromToc Filenames pulled from toc.yaml + * @param {boolean} shouldRemove Should just remove the file + */ +function checkForUnlistedFiles(filenamesFromToc, shouldRemove) { + return fs.readdir(docPath).then(files => { + const htmlFiles = files + .filter(filename => filename.slice(-4) === 'html'); + const removePromises = []; + htmlFiles.forEach(filename => { + if ( + !filenamesFromToc.includes(filename) && + filename !== 'index' && + filename !== 'globals' + ) { + if (shouldRemove) { + console.log( + `REMOVING ${docPath}/${filename} - not listed in toc.yaml.` + ); + removePromises.push(fs.unlink(`${docPath}/${filename}`)); + } else { + // This is just a warning, it doesn't need to finish before + // the process continues. + console.warn( + `Unlisted file: ${filename} generated ` + + `but not listed in toc.yaml.` + ); + } + } + }); + if (shouldRemove) { + return Promise.all(removePromises).then(() => + htmlFiles.filter(filename => filenamesFromToc.includes(filename)) + ); + } else { + return htmlFiles; + } + }); +} + +/** + * Writes a _toc_autogenerated.yaml as a record of all files that were + * autogenerated. Helpful to tech writers. + * + * @param {Array} htmlFiles List of html files found in generated dir. + */ +function writeGeneratedFileList(htmlFiles) { + const fileList = htmlFiles.map(filename => { + return { + title: filename, + path: `${devsitePath}${filename}` + }; + }); + const generatedTocYAML = yaml.safeDump({ toc: fileList }); + return fs + .writeFile(`${docPath}/_toc_autogenerated.yaml`, generatedTocYAML) + .then(() => htmlFiles); +} + +/** + * Fix all links in generated files to other generated files to point to top + * level of generated docs dir. + * + * @param {Array} htmlFiles List of html files found in generated dir. + */ +function fixAllLinks(htmlFiles) { + const writePromises = []; + htmlFiles.forEach(file => { + // Update links in each html file to match flattened file structure. + writePromises.push(fixLinks(`${docPath}/${file}`)); + }); + return Promise.all(writePromises); +} + +/** + * Main document generation process. + * + * Steps for generating documentation: + * 1) Create temporary md file as source of homepage. + * 2) Run Typedoc, sourcing index.d.ts for API content and temporary md file + * for index.html content. + * 3) Write table of contents file. + * 4) Flatten file structure by moving all items up to root dir and fixing + * links as needed. + * 5) Check for mismatches between TOC list and generated file list. + */ +Promise.all([ + fs.readFile(`${contentPath}/toc.yaml`, 'utf8'), + fs.readFile(`${contentPath}/HOME.md`, 'utf8') +]) + // Read TOC and homepage text and assemble a homepage markdown file. + // This file will be sourced by Typedoc to generate index.html. + .then(([tocRaw, homeRaw]) => { + tocText = tocRaw; + return generateTempHomeMdFile(tocRaw, homeRaw); + }) + // Run main Typedoc process (uses index.d.ts and generated temp file above). + .then(runTypedoc) + .then(output => { + // Typedoc output. + console.log(output.stdout); + // Clean up temp home markdown file. (Nothing needs to wait for this.) + fs.unlink(tempHomePath); + // Devsite doesn't like css.map files. + return fs.unlink(`${docPath}/assets/css/main.css.map`); + }) + // Write out TOC file. Do this after Typedoc step to prevent Typedoc + // erroring when it finds an unexpected file in the target dir. + .then(() => fs.writeFile(`${docPath}/_toc.yaml`, tocText)) + // Flatten file structure. These categories don't matter to us and it makes + // it easier to manage the docs directory. + .then(() => { + return Promise.all([ + moveFilesToRoot('classes'), + moveFilesToRoot('modules'), + moveFilesToRoot('interfaces'), + ]); + }) + // Rename files to remove the underscores since devsite hides those. + .then(renameFiles) + // Check for files listed in TOC that are missing and warn if so. + // Not blocking. + .then(checkForMissingFilesAndFixFilenameCase) + // Check for files that exist but aren't listed in the TOC and warn. + // (If API is node, actually remove the file.) + // Removal is blocking, warnings aren't. + .then(filenamesFromToc => + checkForUnlistedFiles(filenamesFromToc, false) + ) + // Write a _toc_autogenerated.yaml to record what files were created. + .then(htmlFiles => writeGeneratedFileList(htmlFiles)) + // Correct the links in all the generated html files now that files have + // all been moved to top level. + // .then(removeUnderscores) + .then(fixAllLinks) + .then(() => { + fs.readFile(`${docPath}/index.html`, 'utf8').then(data => { + // String to include devsite local variables. + const localVariablesIncludeString = `{% include "docs/web/_local_variables.html" %}\n`; + return fs.writeFile( + `${docPath}/index.html`, + localVariablesIncludeString + data + ); + }); + }) + .catch(e => { + if (e.stdout) { + console.error(e.stdout); + } else { + console.error(e); + } + }); diff --git a/docgen/theme/assets/css/firebase.css b/docgen/theme/assets/css/firebase.css new file mode 100644 index 000000000..86c592820 --- /dev/null +++ b/docgen/theme/assets/css/firebase.css @@ -0,0 +1,40 @@ +.firebase-docs .project-name { + color: #333; + display: inline-block; + font-size: 20px; + font-weight: normal; + margin-left: 130px; +} + +.firebase-docs aside.tsd-sources { + padding: 8px; +} + +.firebase-docs .tsd-panel li { + margin: 0; +} + +.firebase-docs aside.tsd-sources:before { + content: unset; +} + +.firebase-docs dl.tsd-comment-tags dt.tag-example { + float: none; + text-transform: capitalize; + color: #000; + font-size: 1.1em; + padding: 5px; + border: none; +} + +.firebase-docs dl.tsd-comment-tags dd.tag-body-example { + padding-left: 0; +} + +.firebase-docs .tsd-breadcrumb .breadcrumb-name a { + color: #039be5; +} + +.firebase-docs .tsd-breadcrumb .model-name { + color: #333; +} \ No newline at end of file diff --git a/docgen/theme/assets/css/main.css b/docgen/theme/assets/css/main.css new file mode 100644 index 000000000..12f3d05d9 --- /dev/null +++ b/docgen/theme/assets/css/main.css @@ -0,0 +1,552 @@ +/*! normalize.css v1.1.3 | MIT License | git.io/normalize */ +/* ========================================================================== HTML5 display definitions ========================================================================== */ +/** Correct `block` display not defined in IE 6/7/8/9 and Firefox 3. */ +article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } + +/** Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. */ +audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } + +/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */ +audio:not([controls]) { display: none; height: 0; } + +/** Address styling not present in IE 7/8/9, Firefox 3, and Safari 4. Known issue: no IE 6 support. */ +[hidden] { display: none; } + +/* ========================================================================== Base ========================================================================== */ +/** 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using `em` units. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */ +html { font-size: 100%; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ font-family: sans-serif; } + +/** Address `font-family` inconsistency between `textarea` and other form elements. */ +button, input, select, textarea { font-family: sans-serif; } + +/** Address margins handled incorrectly in IE 6/7. */ +body { margin: 0; } + +/* ========================================================================== Links ========================================================================== */ +/** Address `outline` inconsistency between Chrome and other browsers. */ +a:focus { outline: thin dotted; } +a:active, a:hover { outline: 0; } + +/** Improve readability when focused and also mouse hovered in all browsers. */ +/* ========================================================================== Typography ========================================================================== */ +/** Address font sizes and margins set differently in IE 6/7. Address font sizes within `section` and `article` in Firefox 4+, Safari 5, and Chrome. */ +h1 { font-size: 2em; margin: 0.67em 0; } + +h2 { font-size: 1.5em; margin: 0.83em 0; } + +h3 { font-size: 1.17em; margin: 1em 0; } + +h4, .tsd-index-panel h3 { font-size: 1em; margin: 1.33em 0; } + +h5 { font-size: 0.83em; margin: 1.67em 0; } + +h6 { font-size: 0.67em; margin: 2.33em 0; } + +/** Address styling not present in IE 7/8/9, Safari 5, and Chrome. */ +abbr[title] { border-bottom: 1px dotted; } + +/** Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. */ +b, strong { font-weight: bold; } + +blockquote { margin: 1em 40px; } + +/** Address styling not present in Safari 5 and Chrome. */ +dfn { font-style: italic; } + +/** Address differences between Firefox and other browsers. Known issue: no IE 6/7 normalization. */ +hr { box-sizing: content-box; height: 0; } + +/** Address styling not present in IE 6/7/8/9. */ +mark { background: #ff0; color: #000; } + +/** Address margins set differently in IE 6/7. */ +p, pre { margin: 1em 0; } + +/** Improve readability of pre-formatted text in all browsers. */ +pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } + +/** Address CSS quotes not supported in IE 6/7. */ +q { quotes: none; } +q:before, q:after { content: ""; content: none; } + +/** Address `quotes` property not supported in Safari 4. */ +/** Address inconsistent and variable font size in all browsers. */ +small { font-size: 80%; } + +/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */ +sub { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } + +sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; top: -0.5em; } + +sub { bottom: -0.25em; } + +/* ========================================================================== Lists ========================================================================== */ +dd { margin: 0 0 0 40px; } + +/** Address paddings set differently in IE 6/7. */ +menu, ol, ul { padding: 0 0 0 40px; } + +/** Correct list images handled incorrectly in IE 7. */ +nav ul, nav ol { list-style: none; list-style-image: none; } + +/* ========================================================================== Embedded content ========================================================================== */ +/** 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3. 2. Improve image quality when scaled in IE 7. */ +img { border: 0; /* 1 */ -ms-interpolation-mode: bicubic; } + +/* 2 */ +/** Correct overflow displayed oddly in IE 9. */ +svg:not(:root) { overflow: hidden; } + +/* ========================================================================== Figures ========================================================================== */ +/** Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11. */ +figure, form { margin: 0; } + +/* ========================================================================== Forms ========================================================================== */ +/** Correct margin displayed oddly in IE 6/7. */ +/** Define consistent border, margin, and padding. */ +fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } + +/** 1. Correct color not being inherited in IE 6/7/8/9. 2. Correct text not wrapping in Firefox 3. 3. Correct alignment displayed oddly in IE 6/7. */ +legend { border: 0; /* 1 */ padding: 0; white-space: normal; /* 2 */ *margin-left: -7px; } + +/* 3 */ +/** 1. Correct font size not being inherited in all browsers. 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5, and Chrome. 3. Improve appearance and consistency in all browsers. */ +button, input, select, textarea { font-size: 100%; /* 1 */ margin: 0; /* 2 */ vertical-align: baseline; /* 3 */ *vertical-align: middle; } + +/* 3 */ +/** Address Firefox 3+ setting `line-height` on `input` using `!important` in the UA stylesheet. */ +button, input { line-height: normal; } + +/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+. Correct `select` style inheritance in Firefox 4+ and Opera. */ +button, select { text-transform: none; } + +/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. 4. Remove inner spacing in IE 7 without affecting normal text inputs. Known issue: inner spacing remains in IE 6. */ +button, html input[type="button"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ *overflow: visible; } + +/* 4 */ +input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ *overflow: visible; } + +/* 4 */ +/** Re-set default cursor for disabled elements. */ +button[disabled], html input[disabled] { cursor: default; } + +/** 1. Address box sizing set to content-box in IE 8/9. 2. Remove excess padding in IE 8/9. 3. Remove excess padding in IE 7. Known issue: excess padding remains in IE 6. */ +input { /* 3 */ } +input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ *height: 13px; /* 3 */ *width: 13px; } +input[type="search"] { -webkit-appearance: textfield; /* 1 */ /* 2 */ box-sizing: content-box; } +input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } + +/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */ +/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */ +/** Remove inner padding and border in Firefox 3+. */ +button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } + +/** 1. Remove default vertical scrollbar in IE 6/7/8/9. 2. Improve readability and alignment in all browsers. */ +textarea { overflow: auto; /* 1 */ vertical-align: top; } + +/* 2 */ +/* ========================================================================== Tables ========================================================================== */ +/** Remove most spacing between table cells. */ +table { border-collapse: collapse; border-spacing: 0; } + +.hljs { display: inline-block; padding: 0.5em; background: white; color: #37474f; } + +.hljs-comment, +.hljs-annotation, +.hljs-template_comment, +.diff .hljs-header, +.hljs-chunk, +.apache .hljs-cbracket { color: #d81b60; } + +.hljs-keyword, +.hljs-id, +.hljs-built_in, +.css .smalltalk .hljs-class, +.hljs-winutils, +.bash .hljs-variable, +.tex .hljs-command, +.hljs-request, +.hljs-status, +.hljs-meta, +.nginx .hljs-title { color: #3b78e7; } + +.xml .hljs-tag { color: #3b78e7; } +.xml .hljs-tag .hljs-value { color: #3b78e7; } + +.hljs-string, +.hljs-title, +.hljs-parent, +.hljs-tag .hljs-value, +.hljs-rules .hljs-value { color: #0d904f; } + +.devsite-dark-code .hljs { display: inline-block; padding: 0.5em; background: white; color: #eceff1; } + +.devsite-dark-code .hljs-comment, +.devsite-dark-code .hljs-annotation, +.devsite-dark-code .hljs-template_comment, +.devsite-dark-code .diff .hljs-header, +.devsite-dark-code .hljs-chunk { color: #f06292; } + +.devsite-dark-code .hljs-keyword, +.devsite-dark-code .hljs-id, +.devsite-dark-code .hljs-built_in, +.devsite-dark-code .hljs-winutils, +.devsite-dark-code .hljs-request, +.devsite-dark-code .hljs-status, +.devsite-dark-code .hljs-meta { color: #4dd0e1; } + +.devsite-dark-code .hljs-string, +.devsite-dark-code .hljs-title, +.devsite-dark-code .hljs-parent, +.devsite-dark-code .hljs-tag .hljs-value, +.devsite-dark-code .hljs-rules .hljs-value { color: #9ccc65; } + +.col > :first-child, .col-1 > :first-child, .col-2 > :first-child, .col-3 > :first-child, .col-4 > :first-child, .col-5 > :first-child, .col-6 > :first-child, .col-7 > :first-child, .col-8 > :first-child, .col-9 > :first-child, .col-10 > :first-child, .col-11 > :first-child, .tsd-panel > :first-child, ul.tsd-descriptions > li > :first-child, .col > :first-child > :first-child, .col-1 > :first-child > :first-child, .col-2 > :first-child > :first-child, .col-3 > :first-child > :first-child, .col-4 > :first-child > :first-child, .col-5 > :first-child > :first-child, .col-6 > :first-child > :first-child, .col-7 > :first-child > :first-child, .col-8 > :first-child > :first-child, .col-9 > :first-child > :first-child, .col-10 > :first-child > :first-child, .col-11 > :first-child > :first-child, .tsd-panel > :first-child > :first-child, ul.tsd-descriptions > li > :first-child > :first-child, .col > :first-child > :first-child > :first-child, .col-1 > :first-child > :first-child > :first-child, .col-2 > :first-child > :first-child > :first-child, .col-3 > :first-child > :first-child > :first-child, .col-4 > :first-child > :first-child > :first-child, .col-5 > :first-child > :first-child > :first-child, .col-6 > :first-child > :first-child > :first-child, .col-7 > :first-child > :first-child > :first-child, .col-8 > :first-child > :first-child > :first-child, .col-9 > :first-child > :first-child > :first-child, .col-10 > :first-child > :first-child > :first-child, .col-11 > :first-child > :first-child > :first-child, .tsd-panel > :first-child > :first-child > :first-child, ul.tsd-descriptions > li > :first-child > :first-child > :first-child { margin-top: 0; } +.col > :last-child, .col-1 > :last-child, .col-2 > :last-child, .col-3 > :last-child, .col-4 > :last-child, .col-5 > :last-child, .col-6 > :last-child, .col-7 > :last-child, .col-8 > :last-child, .col-9 > :last-child, .col-10 > :last-child, .col-11 > :last-child, .tsd-panel > :last-child, ul.tsd-descriptions > li > :last-child, .col > :last-child > :last-child, .col-1 > :last-child > :last-child, .col-2 > :last-child > :last-child, .col-3 > :last-child > :last-child, .col-4 > :last-child > :last-child, .col-5 > :last-child > :last-child, .col-6 > :last-child > :last-child, .col-7 > :last-child > :last-child, .col-8 > :last-child > :last-child, .col-9 > :last-child > :last-child, .col-10 > :last-child > :last-child, .col-11 > :last-child > :last-child, .tsd-panel > :last-child > :last-child, ul.tsd-descriptions > li > :last-child > :last-child, .col > :last-child > :last-child > :last-child, .col-1 > :last-child > :last-child > :last-child, .col-2 > :last-child > :last-child > :last-child, .col-3 > :last-child > :last-child > :last-child, .col-4 > :last-child > :last-child > :last-child, .col-5 > :last-child > :last-child > :last-child, .col-6 > :last-child > :last-child > :last-child, .col-7 > :last-child > :last-child > :last-child, .col-8 > :last-child > :last-child > :last-child, .col-9 > :last-child > :last-child > :last-child, .col-10 > :last-child > :last-child > :last-child, .col-11 > :last-child > :last-child > :last-child, .tsd-panel > :last-child > :last-child > :last-child, ul.tsd-descriptions > li > :last-child > :last-child > :last-child { margin-bottom: 0; } + +.container { max-width: 1200px; margin: 0 auto; padding: 0 40px; } +@media (max-width: 640px) { .container { padding: 0 20px; } } + +.container-main { padding-bottom: 200px; } + +.row { position: relative; margin: 0 -10px; } +.row:after { visibility: hidden; display: block; content: ""; clear: both; height: 0; } + +.col, .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11 { box-sizing: border-box; float: left; padding: 0 10px; } + +.col-1 { width: 8.33333%; } + +.offset-1 { margin-left: 8.33333%; } + +.col-2 { width: 16.66667%; } + +.offset-2 { margin-left: 16.66667%; } + +.col-3 { width: 25%; } + +.offset-3 { margin-left: 25%; } + +.col-4 { width: 33.33333%; } + +.offset-4 { margin-left: 33.33333%; } + +.col-5 { width: 41.66667%; } + +.offset-5 { margin-left: 41.66667%; } + +.col-6 { width: 50%; } + +.offset-6 { margin-left: 50%; } + +.col-7 { width: 58.33333%; } + +.offset-7 { margin-left: 58.33333%; } + +.col-8 { width: 66.66667%; } + +.offset-8 { margin-left: 66.66667%; } + +.col-9 { width: 75%; } + +.offset-9 { margin-left: 75%; } + +.col-10 { width: 83.33333%; } + +.offset-10 { margin-left: 83.33333%; } + +.col-11 { width: 91.66667%; } + +.offset-11 { margin-left: 91.66667%; } + +.tsd-kind-icon { display: block; position: relative; padding-left: 20px; text-indent: -20px; } + +.no-transition { transition: none !important; } + +@-webkit-keyframes fade-in { from { opacity: 0; } + to { opacity: 1; } } + +@keyframes fade-in { from { opacity: 0; } + to { opacity: 1; } } +@-webkit-keyframes fade-out { from { opacity: 1; visibility: visible; } + to { opacity: 0; } } +@keyframes fade-out { from { opacity: 1; visibility: visible; } + to { opacity: 0; } } +@-webkit-keyframes fade-in-delayed { 0% { opacity: 0; } + 33% { opacity: 0; } + 100% { opacity: 1; } } +@keyframes fade-in-delayed { 0% { opacity: 0; } + 33% { opacity: 0; } + 100% { opacity: 1; } } +@-webkit-keyframes fade-out-delayed { 0% { opacity: 1; visibility: visible; } + 66% { opacity: 0; } + 100% { opacity: 0; } } +@keyframes fade-out-delayed { 0% { opacity: 1; visibility: visible; } + 66% { opacity: 0; } + 100% { opacity: 0; } } +@-webkit-keyframes shift-to-left { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); } + to { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } } +@keyframes shift-to-left { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); } + to { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } } +@-webkit-keyframes unshift-to-left { from { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } + to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } } +@keyframes unshift-to-left { from { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } + to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } } +@-webkit-keyframes pop-in-from-right { from { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } + to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } } +@keyframes pop-in-from-right { from { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } + to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } } +@-webkit-keyframes pop-out-to-right { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); visibility: visible; } + to { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } } +@keyframes pop-out-to-right { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); visibility: visible; } + to { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } } + +a { color: #4da6ff; text-decoration: none; } +a:hover { text-decoration: underline; } + +pre { padding: 10px; } +pre code { padding: 0; font-size: 100%; background-color: transparent; } + +.tsd-typography ul { list-style: square; padding: 0 0 0 20px; margin: 0; } +.tsd-typography h4, .tsd-typography .tsd-index-panel h3, .tsd-index-panel .tsd-typography h3, .tsd-typography h5, .tsd-typography h6 { font-size: 1em; margin: 0; } +.tsd-typography h5, .tsd-typography h6 { font-weight: normal; } +.tsd-typography p, .tsd-typography ul, .tsd-typography ol { margin: 1em 0; } + +@media (min-width: 901px) and (max-width: 1024px) { html.default .col-content { width: 72%; } + html.default .col-menu { width: 28%; } + html.default .tsd-navigation { padding-left: 10px; } } +@media (max-width: 900px) { html.default .col-content { float: none; width: 100%; } + html.default .col-menu { position: fixed !important; overflow: auto; -webkit-overflow-scrolling: touch; overflow-scrolling: touch; z-index: 1024; top: 0 !important; bottom: 0 !important; left: auto !important; right: 0 !important; width: 100%; padding: 20px 20px 0 0; max-width: 450px; visibility: hidden; background-color: #fff; -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } + html.default .col-menu > *:last-child { padding-bottom: 20px; } + html.default .overlay { content: ""; display: block; position: fixed; z-index: 1023; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.75); visibility: hidden; } + html.default.to-has-menu .overlay { -webkit-animation: fade-in 0.4s; animation: fade-in 0.4s; } + html.default.to-has-menu header, html.default.to-has-menu footer, html.default.to-has-menu .col-content { -webkit-animation: shift-to-left 0.4s; animation: shift-to-left 0.4s; } + html.default.to-has-menu .col-menu { -webkit-animation: pop-in-from-right 0.4s; animation: pop-in-from-right 0.4s; } + html.default.from-has-menu .overlay { -webkit-animation: fade-out 0.4s; animation: fade-out 0.4s; } + html.default.from-has-menu header, html.default.from-has-menu footer, html.default.from-has-menu .col-content { -webkit-animation: unshift-to-left 0.4s; animation: unshift-to-left 0.4s; } + html.default.from-has-menu .col-menu { -webkit-animation: pop-out-to-right 0.4s; animation: pop-out-to-right 0.4s; } + html.default.has-menu body { overflow: hidden; } + html.default.has-menu .overlay { visibility: visible; } + html.default.has-menu header, html.default.has-menu footer, html.default.has-menu .col-content { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } + html.default.has-menu .col-menu { visibility: visible; -webkit-transform: translate(0, 0); transform: translate(0, 0); } } + +.tsd-page-title { padding: 0; margin: 0; background: #fff; } +.tsd-page-title h1 { font-weight: normal; margin: 0; } + +.tsd-breadcrumb { margin: 0; padding: 0; color: #808080; } +.tsd-breadcrumb a { color: #808080; text-decoration: none; } +.tsd-breadcrumb a:hover { text-decoration: underline; } +.tsd-breadcrumb li { display: inline; margin-right: -0.25em; } + +html.minimal .container { margin: 0; } +html.minimal .container-main { padding-top: 50px; padding-bottom: 0; } +html.minimal .content-wrap { padding-left: 300px; } +html.minimal .tsd-navigation { position: fixed !important; overflow: auto; -webkit-overflow-scrolling: touch; overflow-scrolling: touch; box-sizing: border-box; z-index: 1; left: 0; top: 40px; bottom: 0; width: 300px; padding: 20px; margin: 0; } +html.minimal .tsd-member .tsd-member { margin-left: 0; } +html.minimal .tsd-page-toolbar { position: fixed; z-index: 2; } +html.minimal #tsd-filter .tsd-filter-group { right: 0; -webkit-transform: none; transform: none; } +html.minimal footer { background-color: transparent; } +html.minimal footer .container { padding: 0; } +html.minimal .tsd-generator { padding: 0; } +@media (max-width: 900px) { html.minimal .tsd-navigation { display: none; } + html.minimal .content-wrap { padding-left: 0; } } + +dl.tsd-comment-tags { overflow: hidden; } +dl.tsd-comment-tags dt { clear: both; float: left; padding: 1px 5px; margin: 0 10px 0 0; border-radius: 4px; border: 1px solid #808080; color: #808080; font-size: 0.8em; font-weight: normal; } +dl.tsd-comment-tags dd { margin: 0 0 10px 0; } +dl.tsd-comment-tags p { margin: 0; } + +.tsd-panel.tsd-comment .lead { font-size: 1.1em; line-height: 1.333em; margin-bottom: 2em; } +.tsd-panel.tsd-comment .lead:last-child { margin-bottom: 0; } + +.toggle-protected .tsd-is-private { display: none; } + +.toggle-public .tsd-is-private, .toggle-public .tsd-is-protected, .toggle-public .tsd-is-private-protected { display: none; } + +.toggle-inherited .tsd-is-inherited { display: none; } + +.toggle-only-exported .tsd-is-not-exported { display: none; } + +.toggle-externals .tsd-is-external { display: none; } + +#tsd-filter { position: relative; display: inline-block; height: 40px; vertical-align: bottom; } +.no-filter #tsd-filter { display: none; } +#tsd-filter .tsd-filter-group { display: inline-block; height: 40px; vertical-align: bottom; white-space: nowrap; } +#tsd-filter input { display: none; } +@media (max-width: 900px) { #tsd-filter .tsd-filter-group { display: block; position: absolute; top: 40px; right: 20px; height: auto; background-color: #fff; visibility: hidden; -webkit-transform: translate(50%, 0); transform: translate(50%, 0); box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); } + .has-options #tsd-filter .tsd-filter-group { visibility: visible; } + .to-has-options #tsd-filter .tsd-filter-group { -webkit-animation: fade-in 0.2s; animation: fade-in 0.2s; } + .from-has-options #tsd-filter .tsd-filter-group { -webkit-animation: fade-out 0.2s; animation: fade-out 0.2s; } + #tsd-filter label, #tsd-filter .tsd-select { display: block; padding-right: 20px; } } + +footer { border-top: 1px solid #eee; background-color: #fff; } +footer.with-border-bottom { border-bottom: 1px solid #eee; } +footer .tsd-legend-group { font-size: 0; } +footer .tsd-legend { display: inline-block; width: 25%; padding: 0; font-size: 16px; list-style: none; line-height: 1.333em; vertical-align: top; } +@media (max-width: 900px) { footer .tsd-legend { width: 50%; } } + +.tsd-hierarchy { list-style: square; padding: 0 0 0 20px; margin: 0; } +.tsd-hierarchy .target { font-weight: bold; } + +.tsd-index-panel .tsd-index-content { margin-bottom: -30px !important; } +.tsd-index-panel .tsd-index-section { margin-bottom: 30px !important; } +.tsd-index-panel h3 { margin: 0 -20px 10px -20px; padding: 0 20px 10px 20px; border-bottom: 1px solid #eee; } +.tsd-index-panel ul.tsd-index-list { -webkit-column-count: 3; -moz-column-count: 3; -ms-column-count: 3; -o-column-count: 3; column-count: 3; -webkit-column-gap: 20px; -moz-column-gap: 20px; -ms-column-gap: 20px; -o-column-gap: 20px; column-gap: 20px; padding: 0; list-style: none; line-height: 1.333em; } +@media (max-width: 900px) { .tsd-index-panel ul.tsd-index-list { -webkit-column-count: 1; -moz-column-count: 1; -ms-column-count: 1; -o-column-count: 1; column-count: 1; } } +@media (min-width: 901px) and (max-width: 1024px) { .tsd-index-panel ul.tsd-index-list { -webkit-column-count: 2; -moz-column-count: 2; -ms-column-count: 2; -o-column-count: 2; column-count: 2; } } +.tsd-index-panel ul.tsd-index-list li { -webkit-column-break-inside: avoid; -moz-column-break-inside: avoid; -ms-column-break-inside: avoid; -o-column-break-inside: avoid; column-break-inside: avoid; -webkit-page-break-inside: avoid; -moz-page-break-inside: avoid; -ms-page-break-inside: avoid; -o-page-break-inside: avoid; page-break-inside: avoid; } + +.tsd-flag { display: inline-block; padding: 1px 5px; border-radius: 4px; color: #fff; background-color: #808080; text-indent: 0; font-size: 14px; font-weight: normal; line-height: 1.5em; } + +.tsd-anchor { position: absolute; top: -100px; } + +.tsd-member { position: relative; } +.tsd-member .tsd-anchor + h3 { margin-top: 0; margin-bottom: 0; border-bottom: none; } + +.tsd-navigation { padding: 0 0 0 40px; } +.tsd-navigation a { display: block; padding-top: 2px; padding-bottom: 2px; border-left: 2px solid transparent; color: #222; text-decoration: none; transition: border-left-color 0.1s; } +.tsd-navigation a:hover { text-decoration: underline; } +.tsd-navigation ul { margin: 0; padding: 0; list-style: none; } +.tsd-navigation li { padding: 0; } + +.tsd-navigation.primary { padding-bottom: 40px; } +.tsd-navigation.primary a { display: block; padding-top: 6px; padding-bottom: 6px; } +.tsd-navigation.primary ul li a { padding-left: 5px; } +.tsd-navigation.primary ul li li a { padding-left: 25px; } +.tsd-navigation.primary ul li li li a { padding-left: 45px; } +.tsd-navigation.primary ul li li li li a { padding-left: 65px; } +.tsd-navigation.primary ul li li li li li a { padding-left: 85px; } +.tsd-navigation.primary ul li li li li li li a { padding-left: 105px; } +.tsd-navigation.primary > ul { border-bottom: 1px solid #eee; } +.tsd-navigation.primary li { border-top: 1px solid #eee; } +.tsd-navigation.primary li.current > a { font-weight: bold; } +.tsd-navigation.primary li.label span { display: block; padding: 20px 0 6px 5px; color: #808080; } +.tsd-navigation.primary li.globals + li > span, .tsd-navigation.primary li.globals + li > a { padding-top: 20px; } + +.tsd-navigation.secondary ul { transition: opacity 0.2s; } +.tsd-navigation.secondary ul li a { padding-left: 25px; } +.tsd-navigation.secondary ul li li a { padding-left: 45px; } +.tsd-navigation.secondary ul li li li a { padding-left: 65px; } +.tsd-navigation.secondary ul li li li li a { padding-left: 85px; } +.tsd-navigation.secondary ul li li li li li a { padding-left: 105px; } +.tsd-navigation.secondary ul li li li li li li a { padding-left: 125px; } +.tsd-navigation.secondary ul.current a { border-left-color: #eee; } +.tsd-navigation.secondary li.focus > a, .tsd-navigation.secondary ul.current li.focus > a { border-left-color: #000; } +.tsd-navigation.secondary li.current { margin-top: 20px; margin-bottom: 20px; border-left-color: #eee; } +.tsd-navigation.secondary li.current > a { font-weight: bold; } + +@media (min-width: 901px) { .menu-sticky-wrap { position: static; } + .no-csspositionsticky .menu-sticky-wrap.sticky { position: fixed; } + .no-csspositionsticky .menu-sticky-wrap.sticky-current { position: fixed; } + .no-csspositionsticky .menu-sticky-wrap.sticky-current ul.before-current, .no-csspositionsticky .menu-sticky-wrap.sticky-current ul.after-current { opacity: 0; } + .no-csspositionsticky .menu-sticky-wrap.sticky-bottom { position: absolute; top: auto !important; left: auto !important; bottom: 0; right: 0; } + .csspositionsticky .menu-sticky-wrap.sticky { position: -webkit-sticky; position: sticky; } + .csspositionsticky .menu-sticky-wrap.sticky-current { position: -webkit-sticky; position: sticky; } } + +.tsd-panel { margin: 20px 0; padding: 20px; background-color: #fff; } +.tsd-panel:empty { display: none; } +.tsd-panel > h1, .tsd-panel > h2, .tsd-panel > h3 { margin: 1.5em -20px 10px -20px; padding: 0 20px 10px 20px; border-bottom: 1px solid #ebebeb; } +.tsd-panel > h1.tsd-before-signature, .tsd-panel > h2.tsd-before-signature, .tsd-panel > h3.tsd-before-signature { margin-bottom: 0; border-bottom: 0; } +.tsd-panel table { display: block; width: 100%; overflow: auto; margin-top: 10px; word-break: normal; word-break: keep-all; } +.tsd-panel table th { font-weight: bold; } +.tsd-panel table th, .tsd-panel table td { padding: 6px 13px; border: 1px solid #ddd; } +.tsd-panel table tr { background-color: #fff; border-top: 1px solid #ccc; } +.tsd-panel table tr:nth-child(2n) { background-color: #f8f8f8; } + +.tsd-panel-group { margin: 60px 0; } +.tsd-panel-group > h1, .tsd-panel-group > h2, .tsd-panel-group > h3 { padding-left: 20px; padding-right: 20px; } + +#tsd-search { transition: background-color 0.2s; } +#tsd-search .title { position: relative; z-index: 2; } +#tsd-search .field { position: absolute; left: 0; top: 0; right: 40px; height: 40px; } +#tsd-search .field input { box-sizing: border-box; position: relative; top: -50px; z-index: 1; width: 100%; padding: 0 10px; opacity: 0; outline: 0; border: 0; background: transparent; color: #222; } +#tsd-search .field label { position: absolute; overflow: hidden; right: -40px; } +#tsd-search .field input, #tsd-search .title { transition: opacity 0.2s; } +#tsd-search .results { position: absolute; visibility: hidden; top: 40px; width: 100%; margin: 0; padding: 0; list-style: none; box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); } +#tsd-search .results li { padding: 0 10px; background-color: #fdfdfd; } +#tsd-search .results li:nth-child(even) { background-color: #fff; } +#tsd-search .results li.state { display: none; } +#tsd-search .results li.current, #tsd-search .results li:hover { background-color: #eee; } +#tsd-search .results a { display: block; } +#tsd-search .results a:before { top: 10px; } +#tsd-search .results span.parent { color: #808080; font-weight: normal; } +#tsd-search.has-focus { background-color: #eee; } +#tsd-search.has-focus .field input { top: 0; opacity: 1; } +#tsd-search.has-focus .title { z-index: 0; opacity: 0; } +#tsd-search.has-focus .results { visibility: visible; } +#tsd-search.loading .results li.state.loading { display: block; } +#tsd-search.failure .results li.state.failure { display: block; } + +.tsd-signature { margin: 0 0 1em 0; padding: 10px; border: 1px solid #eee; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; } +.tsd-signature.tsd-kind-icon { padding-left: 30px; } +.tsd-panel > .tsd-signature { margin-left: -20px; margin-right: -20px; border-width: 1px 0; } +.tsd-panel > .tsd-signature.tsd-kind-icon { padding-left: 40px; } + +.tsd-signature-symbol { color: #808080; font-weight: normal; } + +.tsd-signature-type { font-style: italic; font-weight: normal; } + +.tsd-signatures { padding: 0; margin: 0 0 1em 0; border: 1px solid #eee; } +.tsd-signatures .tsd-signature { margin: 0; border-width: 1px 0 0 0; transition: background-color 0.1s; } +.tsd-signatures .tsd-signature:first-child { border-top-width: 0; } +.tsd-signatures .tsd-signature.current { background-color: #eee; } +.tsd-signatures.active > .tsd-signature { cursor: pointer; } +.tsd-panel > .tsd-signatures { margin-left: -20px; margin-right: -20px; border-width: 1px 0; } +.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon { padding-left: 40px; } +.tsd-panel > a.anchor + .tsd-signatures { border-top-width: 0; margin-top: -20px; } + +ul.tsd-descriptions { position: relative; overflow: hidden; transition: height 0.3s; padding: 0; list-style: none; } +ul.tsd-descriptions.active > .tsd-description { display: none; } +ul.tsd-descriptions.active > .tsd-description.current { display: block; } +ul.tsd-descriptions.active > .tsd-description.fade-in { -webkit-animation: fade-in-delayed 0.3s; animation: fade-in-delayed 0.3s; } +ul.tsd-descriptions.active > .tsd-description.fade-out { -webkit-animation: fade-out-delayed 0.3s; animation: fade-out-delayed 0.3s; position: absolute; display: block; top: 0; left: 0; right: 0; opacity: 0; visibility: hidden; } +ul.tsd-descriptions h4, ul.tsd-descriptions .tsd-index-panel h3, .tsd-index-panel ul.tsd-descriptions h3 { font-size: 16px; margin: 1em 0 0.5em 0; } + +ul.tsd-parameters, ul.tsd-type-parameters { list-style: square; margin: 0; padding-left: 20px; } +ul.tsd-parameters > li.tsd-parameter-siganture, ul.tsd-type-parameters > li.tsd-parameter-siganture { list-style: none; margin-left: -20px; } +ul.tsd-parameters h5, ul.tsd-type-parameters h5 { font-size: 16px; margin: 1em 0 0.5em 0; } +ul.tsd-parameters .tsd-comment, ul.tsd-type-parameters .tsd-comment { margin-top: -0.5em; } + +.tsd-sources { font-size: 14px; color: #808080; } +.tsd-sources a { color: #808080; text-decoration: underline; } +.tsd-sources ul, .tsd-sources p { margin: 0 !important; } +.tsd-sources ul { list-style: none; padding: 0; } + +.tsd-page-toolbar { position: absolute; z-index: 1; top: 0; left: 0; width: 100%; height: 40px; color: #333; background: #fff; border-bottom: 1px solid #eee; } +.tsd-page-toolbar a { color: #333; text-decoration: none; } +.tsd-page-toolbar a.title { font-weight: bold; } +.tsd-page-toolbar a.title:hover { text-decoration: underline; } +.tsd-page-toolbar .table-wrap { display: table; width: 100%; height: 40px; } +.tsd-page-toolbar .table-cell { display: table-cell; position: relative; white-space: nowrap; line-height: 40px; } +.tsd-page-toolbar .table-cell:first-child { width: 100%; } + +.tsd-widget:before, .tsd-select .tsd-select-label:before, .tsd-select .tsd-select-list li:before { content: ""; display: inline-block; width: 40px; height: 40px; margin: 0 -8px 0 0; background-image: url(../images/widgets.png); background-repeat: no-repeat; text-indent: -1024px; vertical-align: bottom; } +@media (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { .tsd-widget:before, .tsd-select .tsd-select-label:before, .tsd-select .tsd-select-list li:before { background-image: url(../images/widgets@2x.png); background-size: 320px 40px; } } + +.tsd-widget { display: inline-block; overflow: hidden; opacity: 0.6; height: 40px; transition: opacity 0.1s, background-color 0.2s; vertical-align: bottom; cursor: pointer; } +.tsd-widget:hover { opacity: 0.8; } +.tsd-widget.active { opacity: 1; background-color: #eee; } +.tsd-widget.no-caption { width: 40px; } +.tsd-widget.no-caption:before { margin: 0; } +.tsd-widget.search:before { background-position: 0 0; } +.tsd-widget.menu:before { background-position: -40px 0; } +.tsd-widget.options:before { background-position: -80px 0; } +.tsd-widget.options, .tsd-widget.menu { display: none; } +@media (max-width: 900px) { .tsd-widget.options, .tsd-widget.menu { display: inline-block; } } +input[type=checkbox] + .tsd-widget:before { background-position: -120px 0; } +input[type=checkbox]:checked + .tsd-widget:before { background-position: -160px 0; } + +.tsd-select { position: relative; display: inline-block; height: 40px; transition: opacity 0.1s, background-color 0.2s; vertical-align: bottom; cursor: pointer; } +.tsd-select .tsd-select-label { opacity: 0.6; transition: opacity 0.2s; } +.tsd-select .tsd-select-label:before { background-position: -240px 0; } +.tsd-select.active .tsd-select-label { opacity: 0.8; } +.tsd-select.active .tsd-select-list { visibility: visible; opacity: 1; transition-delay: 0s; } +.tsd-select .tsd-select-list { position: absolute; visibility: hidden; top: 40px; left: 0; margin: 0; padding: 0; opacity: 0; list-style: none; box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); transition: visibility 0s 0.2s, opacity 0.2s; } +.tsd-select .tsd-select-list li { padding: 0 20px 0 0; background-color: #fdfdfd; } +.tsd-select .tsd-select-list li:before { background-position: 40px 0; } +.tsd-select .tsd-select-list li:nth-child(even) { background-color: #fff; } +.tsd-select .tsd-select-list li:hover { background-color: #eee; } +.tsd-select .tsd-select-list li.selected:before { background-position: -200px 0; } +@media (max-width: 900px) { .tsd-select .tsd-select-list { top: 0; left: auto; right: 100%; margin-right: -5px; } + .tsd-select .tsd-select-label:before { background-position: -280px 0; } } + +img { max-width: 100%; } diff --git a/docgen/theme/assets/images/lockup.png b/docgen/theme/assets/images/lockup.png new file mode 100644 index 000000000..f4cdcf24a Binary files /dev/null and b/docgen/theme/assets/images/lockup.png differ diff --git a/docgen/theme/layouts/default.hbs b/docgen/theme/layouts/default.hbs new file mode 100644 index 000000000..72111fb4e --- /dev/null +++ b/docgen/theme/layouts/default.hbs @@ -0,0 +1,33 @@ + + + + + + + + + + {{#ifCond model.name '==' project.name}}{{project.name}}{{else}}{{model.name}} | {{project.name}}{{/ifCond}} + + + + + + + +{{> header}} + +
+
+
+ {{{contents}}} +
+
+
+ +
+ +{{> analytics}} + + + diff --git a/docgen/theme/partials/breadcrumb.hbs b/docgen/theme/partials/breadcrumb.hbs new file mode 100644 index 000000000..db115163f --- /dev/null +++ b/docgen/theme/partials/breadcrumb.hbs @@ -0,0 +1,11 @@ + +{{#if parent}} + {{#with parent}}{{> breadcrumb}}{{/with}} + +{{/if}} \ No newline at end of file diff --git a/docgen/theme/partials/comment.hbs b/docgen/theme/partials/comment.hbs new file mode 100644 index 000000000..f92e54301 --- /dev/null +++ b/docgen/theme/partials/comment.hbs @@ -0,0 +1,22 @@ +{{#with comment}} + {{#if hasVisibleComponent}} +
+ {{#if shortText}} +
+ {{#markdown}}{{{shortText}}}{{/markdown}} +
+ {{/if}} + {{#if text}} + {{#markdown}}{{{text}}}{{/markdown}} + {{/if}} + {{#if tags}} +
+ {{#each tags}} +
{{tagName}}
+
{{#markdown}}{{{text}}}{{/markdown}}
+ {{/each}} +
+ {{/if}} +
+ {{/if}} +{{/with}} \ No newline at end of file diff --git a/docgen/theme/partials/header.hbs b/docgen/theme/partials/header.hbs new file mode 100644 index 000000000..4aee65a6b --- /dev/null +++ b/docgen/theme/partials/header.hbs @@ -0,0 +1,23 @@ +
+
+
+

+ {{#ifCond model.name '==' project.name}} + {{else}} +
    + {{#with model.parent}}{{> breadcrumb}}{{/with}} +
  • {{model.name}}
  • + {{#if model.typeParameters}} + < + {{#each model.typeParameters}} + {{#if @index}}, {{/if}} + {{name}} + {{/each}} + > + {{/if}} +
+ {{/ifCond}} +

+
+
+
\ No newline at end of file diff --git a/docgen/theme/partials/member.sources.hbs b/docgen/theme/partials/member.sources.hbs new file mode 100644 index 000000000..5a0e186f0 --- /dev/null +++ b/docgen/theme/partials/member.sources.hbs @@ -0,0 +1,15 @@ +{{#if implementationOf}} + +{{/if}} +{{#if inheritedFrom}} + +{{/if}} +{{#if overwrites}} + +{{/if}} \ No newline at end of file diff --git a/docgen/theme/partials/navigation.hbs b/docgen/theme/partials/navigation.hbs new file mode 100644 index 000000000..54704739a --- /dev/null +++ b/docgen/theme/partials/navigation.hbs @@ -0,0 +1,22 @@ +{{#if isVisible}} + {{#if isLabel}} +
  • + {{{wbr title}}} +
  • + {{else}} + {{#unless isGlobals}} +
  • + {{{wbr title}}} + {{#if isInPath}} + {{#if children}} + + {{/if}} + {{/if}} +
  • + {{/unless}} + {{/if}} +{{/if}} diff --git a/docgen/theme/templates/reflection.hbs b/docgen/theme/templates/reflection.hbs new file mode 100644 index 000000000..53cd2879a --- /dev/null +++ b/docgen/theme/templates/reflection.hbs @@ -0,0 +1,72 @@ +{{#with model}} + {{#if hasComment}} +
    + {{> comment}} +
    + {{/if}} +{{/with}} + +{{#if model.typeParameters}} +
    +

    Type parameters

    + {{#with model}}{{> typeParameters}}{{/with}} +
    +{{/if}} + +{{#if model.implementedTypes}} +
    +

    Implements

    + +
    +{{/if}} + +{{#if model.implementedBy}} +
    +

    Implemented by

    + +
    +{{/if}} + +{{#if model.signatures}} +
    +

    Callable

    + {{#with model}}{{> member.signatures}}{{/with}} +
    +{{/if}} + +{{#if model.indexSignature}} +
    +

    Indexable

    +
    {{#compact}} + [ + {{#each model.indexSignature.parameters}} + {{name}}: {{#with type}}{{>type}}{{/with}} + {{/each}} + ]:  + {{#with model.indexSignature.type}}{{>type}}{{/with}} + {{/compact}}
    + + {{#with model.indexSignature}} + {{> comment}} + {{/with}} + + {{#if model.indexSignature.type.declaration}} + {{#with model.indexSignature.type.declaration}} + {{> parameter}} + {{/with}} + {{/if}} +
    +{{/if}} + +{{#with model}} + {{> index}} + {{> members}} +{{/with}} \ No newline at end of file diff --git a/docgen/tsconfig.json b/docgen/tsconfig.json new file mode 100644 index 000000000..3c43903cf --- /dev/null +++ b/docgen/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.json" +} diff --git a/docgen/typedoc.js b/docgen/typedoc.js new file mode 100644 index 000000000..58156ff59 --- /dev/null +++ b/docgen/typedoc.js @@ -0,0 +1,27 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const options = { + // includeDeclarations: true, + excludeExternals: true, + ignoreCompilerErrors: true, + name: 'Firebase Functions SDK', + mode: 'modules', + hideGenerator: true +}; + +module.exports = options; diff --git a/package.json b/package.json index 916c4159f..10f0c33d1 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "format:fix": "prettier --write '**/*.{json,md,ts,yml,yaml}'", "lint": "tslint --config tslint.json --project tsconfig.json ", "lint:fix": "tslint --config tslint.json --fix --project tsconfig.json", - "test": "mocha -r ts-node/register ./spec/index.spec.ts" + "test": "mocha -r ts-node/register ./spec/index.spec.ts", + "apidocs": "node docgen/generate-docs.js" }, "dependencies": { "@types/express": "^4.17.0", @@ -51,10 +52,13 @@ "@types/sinon": "^7.0.13", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", + "child-process-promise": "^2.2.1", "firebase-admin": "^8.2.0", "istanbul": "^0.4.5", + "js-yaml": "^3.13.1", "mocha": "^6.1.4", "mock-require": "^3.0.3", + "mz": "^2.7.0", "nock": "^10.0.6", "prettier": "^1.18.2", "sinon": "^7.3.2", @@ -63,7 +67,9 @@ "tslint-config-prettier": "^1.18.0", "tslint-no-unused-expression-chai": "^0.1.4", "tslint-plugin-prettier": "^2.0.1", - "typescript": "^3.5.2" + "typedoc": "^0.14.2", + "typescript": "^3.5.2", + "yargs": "^13.2.4" }, "peerDependencies": { "firebase-admin": "^8.0.0" diff --git a/src/providers/auth.ts b/src/providers/auth.ts index 722410340..7274399b2 100644 --- a/src/providers/auth.ts +++ b/src/providers/auth.ts @@ -116,6 +116,11 @@ export class UserBuilder { */ export type UserRecord = firebase.auth.UserRecord; +/** + * UserInfo that is part of the UserRecord + */ +export type UserInfo = firebase.auth.UserInfo; + export function userRecordConstructor( wireData: Object ): firebase.auth.UserRecord {