Skip to content

Commit

Permalink
feat: implemented auto generation of docs for smapi commands (#70)
Browse files Browse the repository at this point in the history
* feat: implemented auto generation of docs for smapi commands
  • Loading branch information
kakhaUrigashvili authored Apr 7, 2020
1 parent 6ddfa9e commit 9b2f93e
Show file tree
Hide file tree
Showing 9 changed files with 2,404 additions and 0 deletions.
2,189 changes: 2,189 additions & 0 deletions docs/concepts/Smapi-Command.md

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions docs/contributer/Generate-Smapi-Docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generate Smapi Docs

Smapi documentation is auto generated.

Generate docs and save to a file with the following command:

```
node scripts/smapi-docs.js [template-name] > filepath
```
template-name - optional parameter. If not specified 'github' template is used.
All templates are located in the 'lib/commands/smapi/docs-templates'.

Examples:

```
node scripts/smapi-docs.js > docs/concepts/Smapi-Command.md
```

```
node scripts/smapi-docs.js doc-site > Smapi-Command-Doc-Site.md
```
35 changes: 35 additions & 0 deletions lib/commands/smapi/docs-templates/doc-site.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## smapi command {#smapi-command}

{{{smapiCommandDescription}}}

`smapi` command format:

`$ {{baseCommand}} <subcommand> `

## Subcommands

| Task | Subcommand |
|---|---|
{{#commands}}
| {{{description}}} | [{{name}}](#{{name}}-subcommand) |
{{/commands}}
{{#commands}}

#### {{name}} subcommand {#{{name}}-subcommand}

{{description}}

`{{name}}` command format:

`$ {{baseCommand}} {{name}} {{{optionsString}}}`

**Options**
<dl>
{{#options}}
<dt>{{{name}}}</dt>
<dd>{{{description}}}</dd>
{{/options}}
</dl>
{{/commands}}


36 changes: 36 additions & 0 deletions lib/commands/smapi/docs-templates/github.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SMAPI COMMAND

{{{smapiCommandDescription}}}

`smapi` command format:

`$ {{baseCommand}} <subcommand> `

## Subcommands

| Task | Subcommand |
|---|---|
{{#commands}}
| {{{description}}} | [{{name}}](#{{name}}) |
{{/commands}}
{{#commands}}

### {{name}}

{{description}}

`{{name}}` command format:

`$ {{baseCommand}} {{name}} {{{optionsString}}}`

**Options**

<dl>
{{#options}}
<dt>{{{name}}}</dt>
<dd markdown="span">{{{description}}}</dd>
{{/options}}
</dl>
{{/commands}}


47 changes: 47 additions & 0 deletions lib/commands/smapi/smapi-docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const smapiCommandDescription = 'The `smapi` command provides a number of subcommandsthat '
+ 'map 1:1 to the underlying API operations in Alexa Skill Management API (SMAPI).'
+ 'The commands allow detailed control of API inputs and expose raw outputs. '
+ 'There are subcommands for creating and updating the skill, interaction model, '
+ 'and account linking information as well as starting the skill certification process.';

class SmapiDocs {
constructor(commander) {
this.commander = commander;
this.commands = commander.commands;
}

_makeOptionsString(options) {
return options.map(option => {
const { mandatory, flags } = option;
const prefix = mandatory ? '<' : '[';
const suffix = mandatory ? '>' : ']';
return `${prefix}${flags.split(',').join('|')}${suffix}`;
}).join(' ');
}

_cleanDescription(description = '') {
let cleanedDescription = description.trim();
if (cleanedDescription.length > 1 && !cleanedDescription.endsWith('.')) {
cleanedDescription = `${cleanedDescription}.`;
}
// adding new line before * to correctly render list in markdown
return cleanedDescription.replace('*', '\n*');
}

generateViewData() {
const commands = this.commands.map(command => {
const parsedCommand = {
name: command._name,
description: this._cleanDescription(command._description),
optionsString: this._makeOptionsString(command.options),
options: command.options.map(option => ({ name: option.flags, description: this._cleanDescription(option.description) }))
};
return parsedCommand;
});
return { smapiCommandDescription,
baseCommand: 'askx smapi',
commands };
}
}

module.exports = { SmapiDocs };
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"jsonfile": "^2.4.0",
"listr": "^0.14.3",
"module-alias": "^2.1.0",
"mustache": "^4.0.1",
"open": "^7.0.3",
"ora": "^3.4.0",
"portscanner": "^2.1.1",
Expand Down
21 changes: 21 additions & 0 deletions scripts/smapi-docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require('module-alias/register');
const { join } = require('path');
const { readFileSync } = require('fs-extra');
const Mustache = require('mustache');

const { makeSmapiCommander } = require('@src/commands/smapi/smapi-commander');
const { SmapiDocs } = require('@src/commands/smapi/smapi-docs');

const templateName = process.argv[2] || 'github';
const templatePath = join('lib', 'commands', 'smapi', 'docs-templates', `${templateName}.mustache`);
const template = readFileSync(templatePath).toString();

const commander = makeSmapiCommander();

const docs = new SmapiDocs(commander);

const viewData = docs.generateViewData();

const generatedDocs = Mustache.render(template, viewData);

console.log(generatedDocs);
53 changes: 53 additions & 0 deletions test/unit/commands/smapi/smapi-docs-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const { expect } = require('chai');
const { SmapiDocs } = require('@src/commands/smapi/smapi-docs');
const { makeSmapiCommander } = require('@src/commands/smapi/smapi-commander');

describe('Smapi test - Smapi Docs class', () => {
it('| should generate view data from existing smapi commander', () => {
const commander = makeSmapiCommander();

const docs = new SmapiDocs(commander);

const viewData = docs.generateViewData();

expect(viewData.baseCommand).a('string');
expect(viewData.smapiCommandDescription).a('string');
expect(viewData.commands).instanceof(Array);
expect(viewData.commands.length).above(1);
expect(viewData.commands[0].options).instanceof(Array);
});

it('| should generate view data commands list from a commander', () => {
const parentCommandName = 'ask smapi';
const commandName = 'generate-something';
const commandDescription = 'command description';
const optionDescription = 'some option description';
const optionOneFlags = '-c,--catalog-id <catalog-id>';
const optionTwoFlags = '--profile <profile>';
const commander = {
_name: parentCommandName,
commands: [
{
_name: commandName,
_description: commandDescription,
options: [
{ flags: optionOneFlags, description: optionDescription },
{ flags: optionTwoFlags, mandatory: false }
]
}
]
};

const docs = new SmapiDocs(commander);
const viewData = docs.generateViewData();

const expectedCommands = [{ name: commandName,
description: `${commandDescription}.`,
optionsString: '[-c|--catalog-id <catalog-id>] [--profile <profile>]',
options: [
{ name: optionOneFlags, description: `${optionDescription}.` },
{ name: optionTwoFlags, description: '' }] }];

expect(viewData.commands).eql(expectedCommands);
});
});
1 change: 1 addition & 0 deletions test/unit/run-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ require('module-alias/register');
'@test/unit/commands/smapi/cli-customization-processor-test.js',
'@test/unit/commands/smapi/smapi-command-handler-test.js',
'@test/unit/commands/smapi/smapi-commander-test.js',
'@test/unit/commands/smapi/smapi-docs-test.js',
'@test/unit/commands/smapi/customizations/smapi-hooks-test.js',
'@test/unit/commands/smapi/hook-functions/append-vendor-id-test.js',
'@test/unit/commands/smapi/hook-functions/map-testers-emails-test.js',
Expand Down

0 comments on commit 9b2f93e

Please sign in to comment.