diff --git a/.gitignore b/.gitignore index 5d38fa0d..0d912b64 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules/ .tmp aot/ scripts/ionic-native-bower +scripts/docs-json/*.json dist/ src/@ionic-native/plugins/**/ngx *.d.ts diff --git a/package-lock.json b/package-lock.json index e7d94515..cc3d94af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -470,6 +470,18 @@ "@types/node": "*" } }, + "@types/handlebars": { + "version": "4.0.40", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.40.tgz", + "integrity": "sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w==", + "dev": true + }, + "@types/highlight.js": { + "version": "9.12.3", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", + "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", + "dev": true + }, "@types/jest": { "version": "24.0.6", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.6.tgz", @@ -491,6 +503,12 @@ "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==", "dev": true }, + "@types/marked": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz", + "integrity": "sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -513,6 +531,16 @@ "@types/node": "*" } }, + "@types/shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-miY41hqc5SkRlsZDod3heDa4OS9xv8G77EMBQuSpqq86HBn66l7F+f8y9YKm+1PIuwC8QEZVwN8YxOOG7Y67fA==", + "dev": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, "@types/tapable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", @@ -5499,6 +5527,12 @@ "upper-case": "^1.1.3" } }, + "highlight.js": { + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.14.2.tgz", + "integrity": "sha512-Nc6YNECYpxyJABGYJAyw7dBAYbXEuIzwzkqoJnwbc1nIpCiN+3ioYf0XrBnLiyyG0JLuJhpPtt2iTSbXiKLoyA==", + "dev": true + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -10211,6 +10245,12 @@ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -13053,6 +13093,56 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.14.2.tgz", + "integrity": "sha512-aEbgJXV8/KqaVhcedT7xG6d2r+mOvB5ep3eIz1KuB5sc4fDYXcepEEMdU7XSqLFO5hVPu0nllHi1QxX2h/QlpQ==", + "dev": true, + "requires": { + "@types/fs-extra": "^5.0.3", + "@types/handlebars": "^4.0.38", + "@types/highlight.js": "^9.12.3", + "@types/lodash": "^4.14.110", + "@types/marked": "^0.4.0", + "@types/minimatch": "3.0.3", + "@types/shelljs": "^0.8.0", + "fs-extra": "^7.0.0", + "handlebars": "^4.0.6", + "highlight.js": "^9.13.1", + "lodash": "^4.17.10", + "marked": "^0.4.0", + "minimatch": "^3.0.0", + "progress": "^2.0.0", + "shelljs": "^0.8.2", + "typedoc-default-themes": "^0.5.0", + "typescript": "3.2.x" + }, + "dependencies": { + "marked": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz", + "integrity": "sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==", + "dev": true + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + } + } + }, + "typedoc-default-themes": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz", + "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=", + "dev": true + }, "typescript": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", diff --git a/package.json b/package.json index 6a1dcae0..3e95c1ca 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "npmpub": "ts-node -P scripts/tsconfig.json scripts/tasks/publish", "lint": "gulp lint", "readmes": "gulp readmes", + "docs-json": "ts-node -P scripts/tsconfig.json scripts/docs-json", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", "postchangelog": "git commit -am \"chore(): update changelog\"", "shipit": "npm run build && npm run readmes && npm run npmpub" @@ -54,6 +55,7 @@ "ts-node": "^8.0.2", "tslint": "^5.12.1", "tslint-ionic-rules": "0.0.21", + "typedoc": "^0.14.2", "typescript": "3.2.4", "uglifyjs-webpack-plugin": "^2.1.1", "unminified-webpack-plugin": "^2.0.0", diff --git a/scripts/docs-json/index.ts b/scripts/docs-json/index.ts new file mode 100644 index 00000000..f2391d53 --- /dev/null +++ b/scripts/docs-json/index.ts @@ -0,0 +1,99 @@ +import * as fs from 'fs-extra'; +import { Application } from 'typedoc'; +import { basename, dirname, resolve } from 'path'; +import { runInNewContext } from 'vm'; + +interface Plugin { + packageName: string; + displayName: string; + description: string; + platforms: string[]; + usage: string; + repo: string; + cordovaPlugin: { + name: string; + }; +} + +const rootDir = resolve(__dirname, '../..'); +const typedocTmp = resolve(__dirname, 'typedoc.tmp.json'); +const pluginsDir = resolve(rootDir, 'src/@ionic-native/plugins'); +const typedoc = new Application({ + mode: 'modules', + tsconfig: resolve(rootDir, 'tsconfig.json'), + ignoreCompilerErrors: true +}); + +run(pluginsDir); + +async function run(pluginsDir: string) { + const typedocData = await generateTypedoc(pluginsDir); + const modules = typedocData.children.filter(isModule); + const plugins = modules.filter(hasPlugin).map(processPlugin); + await fs.outputJson(resolve(__dirname, 'plugins.json'), plugins, { + spaces: 2 + }); +} + +async function generateTypedoc(root: string, outputPath = typedocTmp) { + const pluginDirs = await fs.readdir(root); + const paths = pluginDirs.map(dir => resolve(root, dir, 'index.ts')); + typedoc.generateJson(paths, outputPath); + return fs.readJson(outputPath); +} + +function processPlugin(pluginModule): Plugin { + const pluginClass = pluginModule.children.find(isPlugin); + const decorator = getPluginDecorator(pluginClass); + const packageName = `@ionic-native/${basename(dirname(pluginModule.originalName))}`; + const displayName = getTag(pluginClass, 'name'); + const usage = getTag(pluginClass, 'usage'); + const description = getTag(pluginClass, 'description'); + return { + packageName, + displayName, + description, + usage, + platforms: decorator.platforms, + repo: decorator.repo, + cordovaPlugin: { + name: decorator.plugin + } + }; +} + +/** + * Typedoc only gives us the Plugin decorator internals + * as a string. So, rather than try to parse that with a RegExp, + * we evaluate it using Node's vm module. + */ +const getPluginDecorator = (child: any) => { + if (isPlugin(child)) { + const decorator = child.decorators.find(d => d.name === 'Plugin'); + return runInNewContext(`(${decorator.arguments.config})`); + } +}; + +const getTag = (child: any, tagName: string): string => { + if (hasTags(child)) { + const tag = child.comment.tags.find(t => t.tag === tagName); + if (tag) { + return tag.text; + } + } +}; + +const isModule = (child: any): boolean => + child.kind === 1; + +const isClass = (child: any): boolean => + child.kind === 128; + +const isPlugin = (child: any): boolean => + isClass(child) && Array.isArray(child.decorators) && child.decorators.some(d => d.name === 'Plugin'); + +const hasPlugin = (child: any): boolean => + child.children.some(isPlugin); + +const hasTags = (child: any): boolean => + child.comment && Array.isArray(child.comment.tags); diff --git a/scripts/docs-json/readme.md b/scripts/docs-json/readme.md new file mode 100644 index 00000000..d714be83 --- /dev/null +++ b/scripts/docs-json/readme.md @@ -0,0 +1,3 @@ +# docs-json + +This script reads and generates [typedoc](https://github.com/TypeStrong/typedoc) data for each of the plugins in `src/@ionic-native/plugins`. That data is then formatted and output as `plugins.json` in this directory. \ No newline at end of file