mirror of
https://github.com/appium/appium.git
synced 2026-11-03 07:34:36 +08:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ca1581870 | ||
|
|
6aec50b074 | ||
|
|
426830d14a | ||
|
|
9538c34131 | ||
|
|
5d24ea1ad2 | ||
|
|
db73971018 | ||
|
|
7b17754786 | ||
|
|
ba07d2a854 |
@@ -10,12 +10,6 @@
|
||||
"files": "packages/*/test/**/*",
|
||||
"rules": {"func-names": "off"}
|
||||
},
|
||||
{
|
||||
"files": ["packages/*/index.js", "packages/*/scripts/**/*.js", "test/*.js"],
|
||||
"parserOptions": {
|
||||
"sourceType": "script"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"packages/appium/support.js",
|
||||
@@ -27,9 +21,17 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["./test/setup.js", "./**/scripts/**/*.js", "./packages/*/index.js"],
|
||||
"files": [
|
||||
"./test/setup.js",
|
||||
"./**/scripts/**/*.js",
|
||||
"./packages/*/index.js",
|
||||
"./packages/docutils/bin/appium-docs.js"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "script"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Generated
+17
-5
@@ -22614,13 +22614,13 @@
|
||||
}
|
||||
},
|
||||
"packages/appium": {
|
||||
"version": "2.0.0-beta.68",
|
||||
"version": "2.0.0-beta.69",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@appium/base-driver": "^9.3.9",
|
||||
"@appium/base-plugin": "^2.2.9",
|
||||
"@appium/docutils": "^0.3.11",
|
||||
"@appium/docutils": "^0.3.12",
|
||||
"@appium/schema": "^0.2.6",
|
||||
"@appium/support": "^4.0.1",
|
||||
"@appium/types": "^0.11.1",
|
||||
@@ -22915,13 +22915,14 @@
|
||||
},
|
||||
"packages/docutils": {
|
||||
"name": "@appium/docutils",
|
||||
"version": "0.3.11",
|
||||
"version": "0.3.12",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@appium/support": "^4.0.1",
|
||||
"@appium/tsconfig": "^0.3.0",
|
||||
"@appium/typedoc-plugin-appium": "^0.6.4",
|
||||
"@sliphua/lilconfig-ts-loader": "3.2.2",
|
||||
"@types/which": "3.0.0",
|
||||
"chalk": "4.1.2",
|
||||
"consola": "2.15.3",
|
||||
"diff": "5.1.0",
|
||||
@@ -22946,13 +22947,18 @@
|
||||
"yargs-parser": "21.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"appium-docs": "build/lib/cli/index.js"
|
||||
"appium-docs": "bin/appium-docs.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
"npm": ">=8"
|
||||
}
|
||||
},
|
||||
"packages/docutils/node_modules/@types/which": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.0.tgz",
|
||||
"integrity": "sha512-ASCxdbsrwNfSMXALlC3Decif9rwDMu+80KGp5zI2RLRotfMsTv7fHL8W8VDp24wymzDyIFudhUeSCugrgRFfHQ=="
|
||||
},
|
||||
"packages/docutils/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"license": "MIT",
|
||||
@@ -23696,6 +23702,7 @@
|
||||
"@appium/tsconfig": "^0.3.0",
|
||||
"@appium/typedoc-plugin-appium": "^0.6.4",
|
||||
"@sliphua/lilconfig-ts-loader": "3.2.2",
|
||||
"@types/which": "3.0.0",
|
||||
"chalk": "4.1.2",
|
||||
"consola": "2.15.3",
|
||||
"diff": "5.1.0",
|
||||
@@ -23720,6 +23727,11 @@
|
||||
"yargs-parser": "21.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/which": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.0.tgz",
|
||||
"integrity": "sha512-ASCxdbsrwNfSMXALlC3Decif9rwDMu+80KGp5zI2RLRotfMsTv7fHL8W8VDp24wymzDyIFudhUeSCugrgRFfHQ=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"requires": {
|
||||
@@ -27794,7 +27806,7 @@
|
||||
"requires": {
|
||||
"@appium/base-driver": "^9.3.9",
|
||||
"@appium/base-plugin": "^2.2.9",
|
||||
"@appium/docutils": "^0.3.11",
|
||||
"@appium/docutils": "^0.3.12",
|
||||
"@appium/schema": "^0.2.6",
|
||||
"@appium/support": "^4.0.1",
|
||||
"@appium/types": "^0.11.1",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.0.0-beta.69](https://github.com/appium/appium/compare/appium@2.0.0-beta.68...appium@2.0.0-beta.69) (2023-05-19)
|
||||
|
||||
**Note:** Version bump only for package appium
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.0-beta.68](https://github.com/appium/appium/compare/appium@2.0.0-beta.67...appium@2.0.0-beta.68) (2023-05-19)
|
||||
|
||||
**Note:** Version bump only for package appium
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "appium",
|
||||
"version": "2.0.0-beta.68",
|
||||
"version": "2.0.0-beta.69",
|
||||
"description": "Automation for Apps.",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -62,7 +62,7 @@
|
||||
"dependencies": {
|
||||
"@appium/base-driver": "^9.3.9",
|
||||
"@appium/base-plugin": "^2.2.9",
|
||||
"@appium/docutils": "^0.3.11",
|
||||
"@appium/docutils": "^0.3.12",
|
||||
"@appium/schema": "^0.2.6",
|
||||
"@appium/support": "^4.0.1",
|
||||
"@appium/types": "^0.11.1",
|
||||
|
||||
@@ -3,6 +3,19 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.3.12](https://github.com/appium/appium/compare/@appium/docutils@0.3.11...@appium/docutils@0.3.12) (2023-05-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docutils:** add @types/which as it is exported ([9538c34](https://github.com/appium/appium/commit/9538c34131cd2f8a3c45039efd65678bc0980497))
|
||||
* **docutils:** exec mike/mkdocs via python -m ([426830d](https://github.com/appium/appium/commit/426830d14a348f163535a7f935a65b028008738d))
|
||||
* **docutils:** provide CJS executable for proper linking ([db73971](https://github.com/appium/appium/commit/db73971018b560ca47527173094720eee3d20a55))
|
||||
* **docutils:** run mkdocs via python -m ([5d24ea1](https://github.com/appium/appium/commit/5d24ea1ad294fa28f7ecce125e5342b081a84c83))
|
||||
* **docutils:** try python3 if python not in PATH ([7b17754](https://github.com/appium/appium/commit/7b177547865a8343625cf089c97cebfb93fd6955))
|
||||
|
||||
|
||||
|
||||
## [0.3.11](https://github.com/appium/appium/compare/@appium/docutils@0.3.10...@appium/docutils@0.3.11) (2023-05-19)
|
||||
|
||||
**Note:** Version bump only for package @appium/docutils
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = require('../build/lib/cli');
|
||||
@@ -13,10 +13,12 @@ import {
|
||||
DEFAULT_SERVE_HOST,
|
||||
DEFAULT_SERVE_PORT,
|
||||
NAME_BIN,
|
||||
NAME_MIKE,
|
||||
NAME_MKDOCS_YML,
|
||||
NAME_PYTHON,
|
||||
} from '../constants';
|
||||
import {DocutilsError} from '../error';
|
||||
import {findMkDocsYml, readPackageJson, whichMike} from '../fs';
|
||||
import {findMkDocsYml, findPython, readPackageJson} from '../fs';
|
||||
import {getLogger} from '../logger';
|
||||
import {argify, spawnBackgroundProcess, SpawnBackgroundProcessOpts, stopwatch} from '../util';
|
||||
|
||||
@@ -24,31 +26,33 @@ const log = getLogger('builder:deploy');
|
||||
|
||||
/**
|
||||
* Runs `mike serve`
|
||||
* @param pythonPath Path to Python 3 executable
|
||||
* @param args Extra args to `mike build`
|
||||
* @param opts Extra options for `teen_process.Subprocess.start`
|
||||
* @param mikePath Path to `mike` executable
|
||||
*/
|
||||
async function doServe(
|
||||
pythonPath: string,
|
||||
args: string[] = [],
|
||||
opts: SpawnBackgroundProcessOpts = {},
|
||||
mikePath?: string
|
||||
opts: SpawnBackgroundProcessOpts = {}
|
||||
) {
|
||||
mikePath = mikePath ?? (await whichMike());
|
||||
const finalArgs = ['serve', ...args];
|
||||
return spawnBackgroundProcess(mikePath, finalArgs, opts);
|
||||
const finalArgs = ['-m,', NAME_MIKE, 'serve', ...args];
|
||||
return spawnBackgroundProcess(pythonPath, finalArgs, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs `mike build`
|
||||
* @param pythonPath Path to Python 3 executable
|
||||
* @param args Extra args to `mike build`
|
||||
* @param opts Extra options to `teen_process.exec`
|
||||
* @param mikePath Path to `mike` executable
|
||||
*/
|
||||
async function doDeploy(args: string[] = [], opts: TeenProcessExecOptions = {}, mikePath?: string) {
|
||||
mikePath = mikePath ?? (await whichMike());
|
||||
const finalArgs = ['deploy', ...args];
|
||||
log.debug('Launching %s with args: %O', mikePath, finalArgs);
|
||||
return await exec(mikePath, finalArgs, opts);
|
||||
async function doDeploy(
|
||||
pythonPath: string,
|
||||
args: string[] = [],
|
||||
opts: TeenProcessExecOptions = {}
|
||||
) {
|
||||
const finalArgs = ['-m', NAME_MIKE, 'deploy', ...args];
|
||||
log.debug('Executing %s via: %s %O', NAME_MIKE, pythonPath, finalArgs);
|
||||
return await exec(pythonPath, finalArgs, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,6 +94,15 @@ export async function deploy({
|
||||
execOpts,
|
||||
}: DeployOpts = {}) {
|
||||
const stop = stopwatch('deploy');
|
||||
|
||||
const pythonPath = await findPython();
|
||||
|
||||
if (!pythonPath) {
|
||||
throw new DocutilsError(
|
||||
`Could not find ${NAME_PYTHON}3/${NAME_PYTHON} executable in PATH; please install Python v3`
|
||||
);
|
||||
}
|
||||
|
||||
mkDocsYmlPath = mkDocsYmlPath ?? (await findMkDocsYml(cwd));
|
||||
if (!mkDocsYmlPath) {
|
||||
throw new DocutilsError(
|
||||
@@ -122,7 +135,7 @@ export async function deploy({
|
||||
}
|
||||
stop(); // discard
|
||||
// unsure about how SIGHUP is handled here
|
||||
await doServe(mikeArgs, serveOpts);
|
||||
await doServe(pythonPath, mikeArgs, serveOpts);
|
||||
} else {
|
||||
log.info('Deploying into branch %s', branch);
|
||||
const mikeArgs = [
|
||||
@@ -137,7 +150,7 @@ export async function deploy({
|
||||
if (alias) {
|
||||
mikeArgs.push(alias);
|
||||
}
|
||||
await doDeploy(mikeArgs, execOpts);
|
||||
await doDeploy(pythonPath, mikeArgs, execOpts);
|
||||
|
||||
log.success('Finished deployment into branch %s (%dms)', branch, stop());
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ export function parseNav(nav: MkDocsYmlNav): ParsedNavData[] {
|
||||
const queue: QueueItem[] = [{entries, keypath: ''}];
|
||||
|
||||
while (queue.length) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const {entries, keypath} = queue.shift()!;
|
||||
for (const [key, item] of entries) {
|
||||
if (_.isString(item)) {
|
||||
@@ -153,6 +154,7 @@ function getRootHeaderKeypath(headerItems: ParsedNavData[], header: string) {
|
||||
// these are the parts of the keypath of the first item, which will contain the header string. it
|
||||
// dosn't matter whether we pick the first one or any one; they will all contain the same root
|
||||
// keypath by definition.
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const rootHeaderKeypathParts = _.toPath(_.first(headerItems)!.keypath);
|
||||
|
||||
// this is the keypath up to the header string, inclusive.
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
import path from 'node:path';
|
||||
import {exec, TeenProcessExecOptions} from 'teen_process';
|
||||
import {DEFAULT_SITE_DIR, NAME_BIN, NAME_MKDOCS_YML} from '../constants';
|
||||
import {DEFAULT_SITE_DIR, NAME_BIN, NAME_MKDOCS, NAME_MKDOCS_YML, NAME_PYTHON} from '../constants';
|
||||
import {DocutilsError} from '../error';
|
||||
import {findMkDocsYml, readMkDocsYml, whichMkDocs} from '../fs';
|
||||
import {findMkDocsYml, findPython, readMkDocsYml} from '../fs';
|
||||
import {getLogger} from '../logger';
|
||||
import {relative, spawnBackgroundProcess, SpawnBackgroundProcessOpts, stopwatch} from '../util';
|
||||
|
||||
@@ -17,37 +17,31 @@ const log = getLogger('mkdocs');
|
||||
|
||||
/**
|
||||
* Runs `mkdocs serve`
|
||||
* @param pythonPath Path to Python 3 executable
|
||||
* @param args Extra args to `mkdocs build`
|
||||
* @param opts Extra options for `teen_process.Subprocess.start`
|
||||
* @param mkDocsPath Path to `mkdocs` executable
|
||||
*/
|
||||
async function doServe(
|
||||
pythonPath: string,
|
||||
args: string[] = [],
|
||||
opts: SpawnBackgroundProcessOpts = {},
|
||||
mkDocsPath?: string
|
||||
opts: SpawnBackgroundProcessOpts = {}
|
||||
) {
|
||||
mkDocsPath = mkDocsPath ?? (await whichMkDocs());
|
||||
const finalArgs = ['serve', ...args];
|
||||
|
||||
log.debug('Launching %s with args: %s', mkDocsPath, finalArgs);
|
||||
return spawnBackgroundProcess(mkDocsPath, finalArgs, opts);
|
||||
const finalArgs = ['-m', NAME_MKDOCS, 'serve', ...args];
|
||||
log.debug('Executing %s via: %s, %O', NAME_MKDOCS, pythonPath, finalArgs);
|
||||
return spawnBackgroundProcess(pythonPath, finalArgs, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs `mkdocs build`
|
||||
* @param pythonPath Path to Python 3 executable
|
||||
* @param args Extra args to `mkdocs build`
|
||||
* @param opts Extra options to `teen_process.exec`
|
||||
* @param mkDocsPath Path to `mkdocs` executable
|
||||
*/
|
||||
async function doBuild(
|
||||
args: string[] = [],
|
||||
opts: TeenProcessExecOptions = {},
|
||||
mkDocsPath?: string
|
||||
) {
|
||||
mkDocsPath = mkDocsPath ?? (await whichMkDocs());
|
||||
const finalArgs = ['build', ...args];
|
||||
log.debug('Launching %s with args: %O', mkDocsPath, finalArgs);
|
||||
return await exec(mkDocsPath, finalArgs, opts);
|
||||
async function doBuild(pythonPath: string, args: string[] = [], opts: TeenProcessExecOptions = {}) {
|
||||
const finalArgs = ['-m', NAME_MKDOCS, 'build', ...args];
|
||||
log.debug('Executing %s via: %s, %O', NAME_MKDOCS, pythonPath, finalArgs);
|
||||
return await exec(pythonPath, finalArgs, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,6 +57,14 @@ export async function buildSite({
|
||||
execOpts,
|
||||
}: BuildMkDocsOpts = {}) {
|
||||
const stop = stopwatch('build-mkdocs');
|
||||
|
||||
const pythonPath = await findPython();
|
||||
if (!pythonPath) {
|
||||
throw new DocutilsError(
|
||||
`Could not find ${NAME_PYTHON}3/${NAME_PYTHON} executable in PATH; please install Python v3`
|
||||
);
|
||||
}
|
||||
|
||||
mkDocsYmlPath = mkDocsYmlPath
|
||||
? path.resolve(process.cwd(), mkDocsYmlPath)
|
||||
: await findMkDocsYml(cwd);
|
||||
@@ -77,10 +79,10 @@ export async function buildSite({
|
||||
}
|
||||
if (serve) {
|
||||
// unsure about how SIGHUP is handled here
|
||||
await doServe(mkdocsArgs, serveOpts);
|
||||
await doServe(pythonPath, mkdocsArgs, serveOpts);
|
||||
} else {
|
||||
log.info('Building site...');
|
||||
await doBuild(mkdocsArgs, execOpts);
|
||||
await doBuild(pythonPath, mkdocsArgs, execOpts);
|
||||
let relSiteDir;
|
||||
if (siteDir) {
|
||||
relSiteDir = relative(cwd, siteDir);
|
||||
|
||||
@@ -50,7 +50,7 @@ const opts = {
|
||||
},
|
||||
'python-path': {
|
||||
defaultDescription: '(derived from shell)',
|
||||
description: 'Path to python 3 executable',
|
||||
description: 'Path to python3 executable',
|
||||
group: ValidateCommandGroup.Paths,
|
||||
nargs: 1,
|
||||
normalize: true,
|
||||
@@ -81,6 +81,15 @@ const opts = {
|
||||
requiresArg: true,
|
||||
type: 'string',
|
||||
},
|
||||
'typedoc-path': {
|
||||
defaultDescription: '(derived from shell)',
|
||||
description: 'Path to typedoc executable',
|
||||
group: ValidateCommandGroup.Paths,
|
||||
nargs: 1,
|
||||
normalize: true,
|
||||
requiresArg: true,
|
||||
type: 'string',
|
||||
},
|
||||
typescript: {
|
||||
default: true,
|
||||
description: 'Validate TypeScript environment',
|
||||
|
||||
+41
-20
@@ -3,27 +3,26 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
import findUp from 'find-up';
|
||||
import YAML from 'yaml';
|
||||
import readPkg, {NormalizedPackageJson, PackageJson} from 'read-pkg';
|
||||
import path from 'node:path';
|
||||
import {JsonValue} from 'type-fest';
|
||||
import {fs} from '@appium/support';
|
||||
import findUp from 'find-up';
|
||||
import * as JSON5 from 'json5';
|
||||
import _ from 'lodash';
|
||||
import path from 'node:path';
|
||||
import _pkgDir from 'pkg-dir';
|
||||
import {getLogger} from './logger';
|
||||
import readPkg, {NormalizedPackageJson, PackageJson} from 'read-pkg';
|
||||
import {JsonValue} from 'type-fest';
|
||||
import {Application, TypeDocReader} from 'typedoc';
|
||||
import YAML from 'yaml';
|
||||
import {
|
||||
NAME_TYPEDOC_JSON,
|
||||
NAME_MKDOCS_YML,
|
||||
NAME_PACKAGE_JSON,
|
||||
NAME_MKDOCS,
|
||||
NAME_NPM,
|
||||
NAME_PACKAGE_JSON,
|
||||
NAME_PYTHON,
|
||||
NAME_MIKE,
|
||||
NAME_TYPEDOC,
|
||||
NAME_TYPEDOC_JSON,
|
||||
} from './constants';
|
||||
import {DocutilsError} from './error';
|
||||
import {getLogger} from './logger';
|
||||
import {MkDocsYml} from './model';
|
||||
|
||||
const log = getLogger('fs');
|
||||
@@ -207,27 +206,49 @@ export function safeWriteFile(filepath: string, content: JsonValue, overwrite =
|
||||
/**
|
||||
* `which` with memoization
|
||||
*/
|
||||
export const cachedWhich = _.memoize(fs.which);
|
||||
|
||||
/**
|
||||
* Finds `mkdocs` executable
|
||||
*/
|
||||
export const whichMkDocs = _.partial(cachedWhich, NAME_MKDOCS);
|
||||
const cachedWhich = _.memoize(fs.which as typeof import('which'));
|
||||
|
||||
/**
|
||||
* Finds `npm` executable
|
||||
*/
|
||||
export const whichNpm = _.partial(cachedWhich, NAME_NPM);
|
||||
export const whichNpm = _.partial(cachedWhich, NAME_NPM, {nothrow: true});
|
||||
|
||||
/**
|
||||
* Finds `python` executable
|
||||
*/
|
||||
export const whichPython = _.partial(cachedWhich, NAME_PYTHON);
|
||||
const whichPython = _.partial(cachedWhich, NAME_PYTHON, {nothrow: true});
|
||||
|
||||
/**
|
||||
* Finds `mike` executable
|
||||
* Finds `python3` executable
|
||||
*/
|
||||
export const whichMike = _.partial(cachedWhich, NAME_MIKE);
|
||||
const whichPython3 = _.partial(cachedWhich, `${NAME_PYTHON}3`, {nothrow: true});
|
||||
|
||||
/**
|
||||
* Finds `typedoc` executable
|
||||
*/
|
||||
const whichTypeDoc = _.partial(cachedWhich, NAME_TYPEDOC, {nothrow: true});
|
||||
|
||||
/**
|
||||
* Finds the `typedoc` executable.
|
||||
*
|
||||
* Looks in the `node_modules/.bin` dir from the current working directory, and if this fails, in the `node_modules` dir for the file which `.bin/typedoc` should be a symlink of, and if _that_ fails, try the `PATH`.
|
||||
*/
|
||||
export const findTypeDoc = _.memoize(async (cwd = process.cwd()): Promise<string | undefined> => {
|
||||
// .cmd is for win32, of course. note that glob _always_ uses posix dir separators.
|
||||
const globResult =
|
||||
(await fs.glob('node_modules/.bin/typedoc?(.cmd)', {cwd, nodir: true})) ??
|
||||
(await fs.glob('node_modules/**/typedoc/bin/typedoc', {cwd, nodir: true, follow: true}));
|
||||
return _.first(globResult) ?? (await whichTypeDoc());
|
||||
});
|
||||
|
||||
/**
|
||||
* Finds the `python3` or `python` executable in the user's `PATH`.
|
||||
*
|
||||
* `python3` is preferred over `python`, since the latter could be Python 2.
|
||||
*/
|
||||
export const findPython = _.memoize(
|
||||
async (): Promise<string | undefined> => (await whichPython3()) ?? (await whichPython())
|
||||
);
|
||||
|
||||
/**
|
||||
* Reads an `mkdocs.yml` file, merges inherited configs, and returns the result. The result is cached.
|
||||
|
||||
@@ -20,7 +20,7 @@ import {createScaffoldTask, ScaffoldTaskOptions} from './scaffold';
|
||||
import {getLogger} from './logger';
|
||||
import {MkDocsYml, TsConfigJson, TypeDocJson} from './model';
|
||||
import _ from 'lodash';
|
||||
import {stringifyJson5, stringifyYaml} from './fs';
|
||||
import {findPython, stringifyJson5, stringifyYaml} from './fs';
|
||||
|
||||
/**
|
||||
* Data for the base `mkdocs.yml` file
|
||||
@@ -158,10 +158,12 @@ export const initMkDocs = createScaffoldTask<InitMkDocsOptions, MkDocsYml>(
|
||||
* @param opts Options
|
||||
*/
|
||||
export async function initPython({
|
||||
pythonPath = NAME_PYTHON,
|
||||
pythonPath,
|
||||
dryRun = false,
|
||||
upgrade = false,
|
||||
}: InitPythonOptions = {}): Promise<void> {
|
||||
pythonPath = pythonPath ?? (await findPython()) ?? NAME_PYTHON;
|
||||
|
||||
const args = ['-m', 'pip', 'install', '-r', REQUIREMENTS_TXT_PATH];
|
||||
if (upgrade) {
|
||||
args.push('--upgrade');
|
||||
|
||||
@@ -6,20 +6,19 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
import figures from 'figures';
|
||||
import logSymbols from 'log-symbols';
|
||||
import chalk, {ForegroundColor, BackgroundColor} from 'chalk';
|
||||
import chalk, {type BackgroundColor, type ForegroundColor} from 'chalk';
|
||||
import consola, {
|
||||
logType as LogType,
|
||||
ConsolaReporterLogObject,
|
||||
type Consola,
|
||||
type ConsolaReporterLogObject,
|
||||
FancyReporter,
|
||||
FancyReporterOptions,
|
||||
Consola,
|
||||
ConsolaOptions,
|
||||
LogLevel,
|
||||
type FancyReporterOptions,
|
||||
type LogLevel,
|
||||
type logType as LogType,
|
||||
} from 'consola';
|
||||
import {DEFAULT_LOG_LEVEL, LogLevelMap} from './constants';
|
||||
import figures from 'figures';
|
||||
import _ from 'lodash';
|
||||
import logSymbols from 'log-symbols';
|
||||
import {DEFAULT_LOG_LEVEL, LogLevelMap} from './constants';
|
||||
|
||||
/**
|
||||
* This is a reporter for `consola` which uses some extra/custom icons and colors.
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import _ from 'lodash';
|
||||
import {SpawnOptions, spawn} from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import type {SubProcess} from 'teen_process';
|
||||
|
||||
/**
|
||||
* Computes a relative path, prepending `./`
|
||||
@@ -26,7 +25,7 @@ export function stopwatch(id: string) {
|
||||
const start = Date.now();
|
||||
stopwatch.cache.set(id, start);
|
||||
return () => {
|
||||
const result = Date.now() - stopwatch.cache.get(id)!;
|
||||
const result = Date.now() - (stopwatch.cache.get(id) ?? 0);
|
||||
stopwatch.cache.delete(id);
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -31,14 +31,14 @@ import {
|
||||
} from './constants';
|
||||
import {DocutilsError} from './error';
|
||||
import {
|
||||
findPkgDir,
|
||||
findMkDocsYml,
|
||||
findPkgDir,
|
||||
findTypeDoc,
|
||||
readJson5,
|
||||
readTypedocJson,
|
||||
whichMkDocs,
|
||||
whichNpm,
|
||||
whichPython,
|
||||
readMkDocsYml,
|
||||
readTypedocJson,
|
||||
whichNpm,
|
||||
findPython,
|
||||
} from './fs';
|
||||
import {getLogger} from './logger';
|
||||
import {MkDocsYml, PipPackage, TypeDocJson} from './model';
|
||||
@@ -62,7 +62,7 @@ const TYPEDOC_VERSION_REGEX = /TypeDoc\s(\d+\.\d+\..+)/;
|
||||
/**
|
||||
* Matches the MkDocs version string from `mkdocs --version`
|
||||
*/
|
||||
const MKDOCS_VERSION_REGEX = /mkdocs,\s+version\s+(\d+\.\d+\.\S+)/;
|
||||
const MKDOCS_VERSION_REGEX = /\s+version\s+(\d+\.\d+\.\S+)/;
|
||||
|
||||
const log = getLogger('validate');
|
||||
|
||||
@@ -95,12 +95,12 @@ export class DocutilsValidator extends EventEmitter {
|
||||
/**
|
||||
* Path to `npm` executable.
|
||||
*/
|
||||
protected readonly npmPath: string | undefined;
|
||||
protected readonly npmPath?: string;
|
||||
|
||||
/**
|
||||
* Path to `python` executable.
|
||||
*/
|
||||
protected readonly pythonPath: string | undefined;
|
||||
protected readonly pythonPath?: string;
|
||||
|
||||
/**
|
||||
* List of validations to perform
|
||||
@@ -120,27 +120,29 @@ export class DocutilsValidator extends EventEmitter {
|
||||
/**
|
||||
* Path to `mkdocs.yml`. If not provided, will be lazily resolved.
|
||||
*/
|
||||
protected mkDocsYmlPath: string | undefined;
|
||||
protected mkDocsYmlPath?: string;
|
||||
|
||||
/**
|
||||
* Path to `package.json`. If not provided, will be lazily resolved.
|
||||
*/
|
||||
protected packageJsonPath: string | undefined;
|
||||
protected packageJsonPath?: string;
|
||||
|
||||
/**
|
||||
* Path to the package directory. If not provided, will be lazily resolved.
|
||||
*/
|
||||
protected pkgDir: string | undefined;
|
||||
protected pkgDir?: string;
|
||||
|
||||
/**
|
||||
* Path to `tsconfig.json`. If not provided, will be lazily resolved.
|
||||
*/
|
||||
protected tsconfigJsonPath: string | undefined;
|
||||
protected tsconfigJsonPath?: string;
|
||||
|
||||
/**
|
||||
* Path to `typedoc.json`. If not provided, will be lazily resolved.
|
||||
*/
|
||||
protected typeDocJsonPath: string | undefined;
|
||||
protected typeDocJsonPath?: string;
|
||||
|
||||
protected typeDocPath?: string;
|
||||
|
||||
/**
|
||||
* Emitted when validation begins with a list of validation kinds to be performed
|
||||
@@ -181,6 +183,7 @@ export class DocutilsValidator extends EventEmitter {
|
||||
this.typeDocJsonPath = opts.typedocJson;
|
||||
this.npmPath = opts.npm;
|
||||
this.mkDocsYmlPath = opts.mkdocsYml;
|
||||
this.typeDocPath = opts.typedocPath;
|
||||
|
||||
if (opts.python) {
|
||||
this.validations.add(NAME_PYTHON);
|
||||
@@ -314,21 +317,19 @@ export class DocutilsValidator extends EventEmitter {
|
||||
* Validates that the correct version of `mkdocs` is installed
|
||||
*/
|
||||
protected async validateMkDocs() {
|
||||
let mkDocsPath: string | undefined;
|
||||
try {
|
||||
mkDocsPath = await whichMkDocs();
|
||||
} catch {
|
||||
// _pretty sure_ the exception code is always ENOENT
|
||||
const pythonPath = this.pythonPath ?? (await findPython());
|
||||
|
||||
if (!pythonPath) {
|
||||
return this.fail(
|
||||
`Could not find ${NAME_MKDOCS} executable in PATH. If it is installed, check your PATH environment variable.`
|
||||
`Could not find ${NAME_PYTHON} executable in PATH. If it is installed, check your PATH environment variable.`
|
||||
);
|
||||
}
|
||||
|
||||
let rawMkDocsVersion: string | undefined;
|
||||
try {
|
||||
({stdout: rawMkDocsVersion} = await exec(mkDocsPath, ['--version']));
|
||||
({stdout: rawMkDocsVersion} = await exec(pythonPath, ['-m', NAME_MKDOCS, '--version']));
|
||||
} catch (err) {
|
||||
return this.fail(`${mkDocsPath} --version failed: ${err}`);
|
||||
return this.fail(`Failed to get MkDocs version: ${err}`);
|
||||
}
|
||||
const match = rawMkDocsVersion.match(MKDOCS_VERSION_REGEX);
|
||||
if (match) {
|
||||
@@ -343,12 +344,12 @@ export class DocutilsValidator extends EventEmitter {
|
||||
const {version: mkDocsReqdVersion} = mkDocsPipPkg;
|
||||
if (version !== mkDocsReqdVersion) {
|
||||
return this.fail(
|
||||
`${NAME_MKDOCS} at ${mkDocsPath} is v${version}, but ${REQUIREMENTS_TXT_PATH} requires v${mkDocsReqdVersion}`
|
||||
`${NAME_MKDOCS} is v${version}, but ${REQUIREMENTS_TXT_PATH} requires v${mkDocsReqdVersion}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new DocutilsError(
|
||||
`Could not parse version from "${mkDocsPath} --version". This is a bug. Output was ${rawMkDocsVersion}`
|
||||
`Could not parse version from MkDocs. This is a bug. Output was ${rawMkDocsVersion}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -423,7 +424,7 @@ export class DocutilsValidator extends EventEmitter {
|
||||
*/
|
||||
protected async validatePythonDeps() {
|
||||
let pipListOutput: string;
|
||||
const pythonPath = this.pythonPath ?? (await whichPython());
|
||||
const pythonPath = this.pythonPath ?? (await findPython());
|
||||
if (!pythonPath) {
|
||||
return this.fail(`Could not find ${NAME_PYTHON} in PATH. Is it installed?`);
|
||||
}
|
||||
@@ -499,7 +500,7 @@ export class DocutilsValidator extends EventEmitter {
|
||||
* Asserts that the Python version is 3.x
|
||||
*/
|
||||
protected async validatePythonVersion() {
|
||||
const pythonPath = this.pythonPath ?? (await whichPython());
|
||||
const pythonPath = this.pythonPath ?? (await findPython());
|
||||
if (!pythonPath) {
|
||||
return this.fail(`Could not find ${NAME_PYTHON} in PATH. Is it installed?`);
|
||||
}
|
||||
@@ -520,17 +521,30 @@ export class DocutilsValidator extends EventEmitter {
|
||||
/**
|
||||
* Asserts TypeDoc is installed, runnable, the correct version, and that the config file is readable
|
||||
* and constaints required options
|
||||
*
|
||||
* @todo Another option would be to `npm exec typedoc@<version>` which delegates to `npx`.
|
||||
*/
|
||||
protected async validateTypeDoc() {
|
||||
const pkgDir = await this.findPkgDir();
|
||||
const typeDocPath = this.typeDocPath ?? (await findTypeDoc(pkgDir));
|
||||
|
||||
if (!typeDocPath) {
|
||||
return this.fail(`Could not find ${NAME_TYPEDOC}; is it installed?`);
|
||||
}
|
||||
log.debug('Found %s at %s', NAME_TYPEDOC, typeDocPath);
|
||||
|
||||
let rawTypeDocVersion: string;
|
||||
let typeDocVersion: string;
|
||||
try {
|
||||
({stdout: rawTypeDocVersion} = await exec('npm', ['exec', NAME_TYPEDOC, '--', '--version'], {
|
||||
({stdout: rawTypeDocVersion} = await exec(process.execPath, [typeDocPath, '--version'], {
|
||||
cwd: pkgDir,
|
||||
}));
|
||||
} catch {
|
||||
return this.fail(`Could not find ${NAME_TYPEDOC} executable from ${pkgDir}`);
|
||||
} catch (err) {
|
||||
return this.fail(
|
||||
`Could not execute ${process.execPath} ${typeDocPath} from ${pkgDir}. Reason: ${
|
||||
(err as Error).message
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
if (rawTypeDocVersion) {
|
||||
@@ -543,7 +557,8 @@ export class DocutilsValidator extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
const reqdTypeDocVersion = DOCUTILS_PKG.dependencies!.typedoc!;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const reqdTypeDocVersion = DOCUTILS_PKG.dependencies!.typedoc!; // this is our own package.json
|
||||
if (!satisfies(typeDocVersion, reqdTypeDocVersion)) {
|
||||
return this.fail(
|
||||
`Found TypeDoc version ${typeDocVersion}, but ${reqdTypeDocVersion} is required`
|
||||
@@ -596,7 +611,7 @@ export class DocutilsValidator extends EventEmitter {
|
||||
if (!typeDocJson.out) {
|
||||
return this.fail(
|
||||
new DocutilsError(
|
||||
`Missing "out" property in ${relTypeDocJsonPath}; path "${DEFAULT_REL_TYPEDOC_OUT_PATH} is recommended`
|
||||
`Missing "out" property in ${relTypeDocJsonPath}; path "${DEFAULT_REL_TYPEDOC_OUT_PATH}" is recommended`
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -714,6 +729,10 @@ export interface DocutilsValidatorOpts {
|
||||
* If `true`, run TypeDoc validation
|
||||
*/
|
||||
typedoc?: boolean;
|
||||
/**
|
||||
* Path to `typedoc` executable
|
||||
*/
|
||||
typedocPath?: string;
|
||||
/**
|
||||
* Path to `typedoc.json`
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/docutils",
|
||||
"version": "0.3.11",
|
||||
"version": "0.3.12",
|
||||
"description": "Documentation generation utilities for Appium and related projects",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -28,7 +28,7 @@
|
||||
"lib": "lib"
|
||||
},
|
||||
"bin": {
|
||||
"appium-docs": "./build/lib/cli/index.js"
|
||||
"appium-docs": "./bin/appium-docs.js"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
@@ -53,6 +53,7 @@
|
||||
"@appium/tsconfig": "^0.3.0",
|
||||
"@appium/typedoc-plugin-appium": "^0.6.4",
|
||||
"@sliphua/lilconfig-ts-loader": "3.2.2",
|
||||
"@types/which": "3.0.0",
|
||||
"chalk": "4.1.2",
|
||||
"consola": "2.15.3",
|
||||
"diff": "5.1.0",
|
||||
|
||||
@@ -6,32 +6,34 @@
|
||||
|
||||
This package leverages [TypeDoc](https://typedoc.org) to generate command documentation (HTTP endpoints, payload information, etc.) for Appium v2+ drivers and plugins.
|
||||
|
||||
## Important Note
|
||||
|
||||
_If you are an Appium extension author and just want to build HTML docs_, **don't install this directly**--instead, install [`@appium/docutils`](https://github.com/appium/appium/tree/master/packages/docutils), which is a higher-level package that configures everything for you.
|
||||
|
||||
If you _only_ want to build markdown docs for your extension, then you can use this package directly.
|
||||
|
||||
## Installation
|
||||
|
||||
`npm` v8+ is required to install this package.
|
||||
|
||||
```bash
|
||||
npm install appium@next typedoc @appium/typedoc-plugin-appium --save-dev
|
||||
npm install @appium/typedoc-plugin-appium --save-dev
|
||||
```
|
||||
|
||||
`typedoc` and `appium` are peer dependencies of this package. Newer versions of `npm` will install these automatically (if possible).
|
||||
The above command installs the plugin as well as all necessary peer dependencies. See [`package.json`](https://github.com/appium/appium/blob/master/packages/docutils/package.json) for the full list of dependencies.
|
||||
|
||||
## Usage
|
||||
|
||||
TypeDoc is configured via a `typedoc.json` or `typedoc.js` file ([read the docs](https://typedoc.org/guides/options/) for more information).
|
||||
|
||||
An Appium extension author wishing to generate documentation for their extension will need to create a `typedoc.json`. At minimum, it should contain:
|
||||
|
||||
> TODO: The plugin should be able to detect the entry points automatically, so this should not be necessary
|
||||
An Appium extension author wishing to generate markdown documentation for their extension will need to create a `typedoc.json`. At minimum, it should contain:
|
||||
|
||||
```json
|
||||
{
|
||||
"entryPointStrategy": "packages",
|
||||
"entryPoints": [
|
||||
"./node_modules/appium",
|
||||
"./node_modules/@appium/base-driver",
|
||||
"./node_modules/@appium/types",
|
||||
"."
|
||||
],
|
||||
"entryPoints": ["."],
|
||||
"name": "<name of extension>",
|
||||
"theme": "appium",
|
||||
"out": "<path to output directory>"
|
||||
}
|
||||
```
|
||||
@@ -42,21 +44,37 @@ Once this file is created, you can run `typedoc` to generate the documentation,
|
||||
|
||||
This plugin supports all of the options from [typedoc-plugin-markdown](https://npm.im/typedoc-plugin-markdown), as well as the following:
|
||||
|
||||
### `commandsDir`
|
||||
### `outputModules`
|
||||
|
||||
> TODO
|
||||
|
||||
### `forceBreadcrumbs`
|
||||
|
||||
> TODO
|
||||
`boolean` - Output module, class, interface, and other type information (the usual TypeDoc output) in addition to command documentation. This is needed for full documentation of types. _Default value: `true`_
|
||||
|
||||
### `outputBuiltinCommands`
|
||||
|
||||
> TODO
|
||||
`boolean` - Outputs _all_ commands and types from Appium builtins--not just your extension. This is intended to be used by Appium itself. _Default value: `false`_
|
||||
|
||||
### `outputModules`
|
||||
### `packageTitles`
|
||||
|
||||
> TODO
|
||||
`Array<{name: string, title: string}>`: An array of objects containing module name `name` and display name `title`. By default, the module name is used for the title; use this to override that behavior. _Default value: `undefined`_
|
||||
|
||||
### `commandsDir`
|
||||
|
||||
`string` - The name of the "commands" directory relative to the TypeDoc output directory (`out`). _Default value: `commands`_
|
||||
|
||||
### `forceBreadcrumbs`
|
||||
|
||||
`boolean` - Forces breadcrumbs to be output; overrides `hideBreadcrumbs` from `typedoc-plugin-markdown`. _Default value: `false`_
|
||||
|
||||
## Development
|
||||
|
||||
This packages uses snapshot tests to assert the generated markdown is correct. If you have made changes which affect the plugin's output, you will need to update the snapshots.
|
||||
|
||||
To update the snapshots, execute:
|
||||
|
||||
```bash
|
||||
UPDATE_SNAPSHOT=1 npm test
|
||||
```
|
||||
|
||||
This will (likely) modify the snapshots in your working copy, so you will then need to commit them.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user