diff --git a/.gitignore b/.gitignore index 8ddd744fb7..41339eb81d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ cypress/videos # Dynamically parsed data source/_data/banners.yml +source/_data/cypress-typedoc.json # Translations # By default we ignore each translation folder like "source/ja", diff --git a/gulpfile.js b/gulpfile.js index 81a9bc4848..5839690d93 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,7 @@ +const execa = require('execa') const gulp = require('gulp') const RevAll = require('gulp-rev-all') +const typedoc = require('gulp-typedoc') const clean = require('gulp-clean') const revisionOpts = { @@ -99,6 +101,26 @@ gulp.task('move:robots.txt:to:public', function () { .pipe(gulp.dest('public')) }) +gulp.task('clone:cypress', function () { + // TODO: control branch name? + return execa.command('git clone --depth 1 --single-branch --branch master https://github.com/cypress-io/cypress.git ./tmp/cypress') +}) + +gulp.task('run:typedoc', function () { + return gulp.src(['./tmp/cypress/cli/types/index.d.ts']) + .pipe(typedoc({ + entryPoint: 'Cypress', + // drastically reduces output size - but we don't get docs for included packages + excludeExternals: true, + ignoreCompilerErrors: true, + includeDeclarations: true, + json: './source/_data/cypress-typedoc.json', + logger: 'console', + mode: 'file', + tsconfig: './tmp/cypress/packages/ts/tsconfig.json', + })) +}) + gulp.task('clean:non:application:js', () => { return remove('public/js/!(application).js') }) @@ -127,7 +149,9 @@ gulp.task('clean:public', () => { gulp.task('copy:static:assets', gulp.parallel('move:menu:spy:js', 'move:scrolling:element:js', 'move:doc:search:js', 'move:doc:yall:js', 'move:doc:search:css', 'move:roboto:fonts', 'move:font:awesome:fonts')) -gulp.task('pre:build', gulp.parallel('copy:static:assets')) +gulp.task('generate:typedoc', gulp.series('clone:cypress', 'run:typedoc')) + +gulp.task('pre:build', gulp.parallel('generate:typedoc', 'copy:static:assets')) gulp.task('post:build', gulp.series('clean:js', 'clean:css', 'clean:fonts:folders', 'revision', 'clean:public', 'copy:tmp:to:public', 'move:robots.txt:to:public', 'clean:tmp')) diff --git a/lib/tags/typedoc.js b/lib/tags/typedoc.js new file mode 100644 index 0000000000..fd985d54ee --- /dev/null +++ b/lib/tags/typedoc.js @@ -0,0 +1,108 @@ +const _ = require('lodash') +const assert = require('assert') +const path = require('path') +const fse = require('fs-extra') +const Promise = require('bluebird') +const rawRender = require('../raw_render') + +const pathToTypeDoc = path.join(__dirname, '../../source/_data/cypress-typedoc.json') + +let getTypeDocPromise + +function _getTypeDoc() { + if (!getTypeDocPromise) { + getTypeDocPromise = fse.readJson(pathToTypeDoc) + } + + return getTypeDocPromise +} + +const knownKindStrings = { + 'cy': 'Interface', + 'Cypress': 'Module' +} + +function _getTypeAtPath(path) { + return _getTypeDoc() + .then((type) => { + path.forEach(name => { + type = _.find(type.children, (child) => { + const knownKindString = knownKindStrings[name] + + return child.name === name && (!knownKindString || child.kindString === knownKindString) + }) + }) + + return type + }) +} + +function _renderInterface(path, interface) { + assert.strictEqual(method.kindString, 'Interface') + let out = 'Option | Default | Description\n' + out += '--- | --- | ---\n' + + out += _.chain(interface.children) + .filter({ kindString: 'Property' }) + .sortBy(_.property('name')) + .map(_renderProperty) + .value() + + return out +} + +function _renderMethod(path, method) { + assert.strictEqual(method.kindString, 'Method') + let out = '' + + out += '## Syntax\n\n' + out += '```javascript\n' + + out += method.signatures + .map(_.partial(_renderSignature, path)) + .join('\n') + + out += '\n```\n\n' + + return out +} + +function _renderParameter(parameter) { + assert.strictEqual(parameter.kindString, 'Parameter') + return `${parameter.name}${parameter.flags.isOptional ? '?' : ''}: ${parameter.type.name}` +} + +function _renderProperty(property) { + assert.strictEqual(property.kindString, 'Property') + return `\`${property.name}\` | \`${property.type.name}\` | ${_renderPropertyComment(property.comment)}` +} + +function _renderPropertyComment(comment) { + if (!comment) { + return '' + } + + const default = _.find(comment.tags, { tag: 'default' }) + + return `${(comment.shortText || '')}${default ? ` (default: \`${default.text}\`)` : ''}` +} + +function _renderSignature(path, signature) { + assert.strictEqual(signature.kindString, 'Call signature') + return `${path}(${signature.parameters ? signature.parameters.map(_renderParameter).join(', ') : ''})` +} + +module.exports = function partial (hexo, [pathString]) { + const path = _.toPath(`Cypress.${pathString}`) + + return _getTypeAtPath(path) + .then((type) => { + const out = ({ + Interface: _renderInterface + Method: _renderMethod, + })[type.kindString](pathString, type) + + console.log(out) + return rawRender(hexo, `
${out}`, { engine: 'markdown' })
+ })
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index a794c8a358..afda730796 100644
--- a/package.json
+++ b/package.json
@@ -106,6 +106,7 @@
"gulp": "4.0.2",
"gulp-clean": "0.4.0",
"gulp-rev-all": "2.0.2",
+ "gulp-typedoc": "2.2.2",
"husky": "3.0.3",
"inquirer": "6.5.0",
"jest": "24.8.0",
@@ -127,6 +128,7 @@
"textlint-filter-rule-comments": "1.2.2",
"textlint-rule-eslint": "3.2.0",
"textlint-rule-terminology": "1.1.30",
+ "typedoc": "0.15.0",
"utf8": "3.0.0",
"wait-on": "3.3.0",
"yamljs": "0.3.0"
diff --git a/scripts/tags.js b/scripts/tags.js
index 7ac454b07e..55c71e8f8f 100644
--- a/scripts/tags.js
+++ b/scripts/tags.js
@@ -10,6 +10,7 @@ const yields = require('../lib/tags/yields')
const requirements = require('../lib/tags/requirements')
const assertions = require('../lib/tags/assertions')
const timeouts = require('../lib/tags/timeouts')
+const typedoc = require('../lib/tags/typedoc')
const usageOptions = require('../lib/tags/usage')
const { issue, PR, openAnIssue, user } = require('../lib/tags/github')
const { badge } = require('../lib/tags/badge')
@@ -22,61 +23,52 @@ const history = require('../lib/tags/history')
const aliases = require('../lib/tags/aliases')
const tags = {
- // aliases
- aliases: aliases,
+ aliases,
- // assertions
- assertions: assertions,
+ assertions,
- // badge
- badge: badge,
+ badge,
- // changelog
- changelog: changelog,
+ changelog,
// icons
- fa: fa,
+ fa,
helper_icon: helperIcon,
-
+
// images
- imgTag: imgTag,
+ imgTag,
// github links
- issue: issue,
+ issue,
open_an_issue: openAnIssue,
- PR: PR,
- user: user,
+ PR,
+ user,
+
+ partial,
- // partials
- partial: partial,
+ requirements,
- // requirements
- requirements: requirements,
+ timeouts,
- // timeouts
- timeouts: timeouts,
+ typedoc,
// url
- url: url,
- urlHash: urlHash,
+ url,
+ urlHash,
- // usage_options
usage_options: usageOptions,
// video
- video: video,
+ video,
- // yields
- yields: yields,
+ yields,
}
// tags which require ending
const endingTags = {
- // history
- history: history,
+ history,
- // note
- note: note,
+ note,
}
function promisify (fn) {