Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 48 additions & 46 deletions aio/tools/transforms/cli-docs-package/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const {resolve} = require('canonical-path');
const semver = require('semver');
const Package = require('dgeni').Package;
const basePackage = require('../angular-base-package');
const contentPackage = require('../content-package');
Expand All @@ -8,59 +9,60 @@ const CLI_SOURCE_PATH = resolve(CLI_SOURCE_ROOT, 'node_modules/@angular/cli');
const CLI_SOURCE_HELP_PATH = resolve(CLI_SOURCE_PATH, 'help');

// Define the dgeni package for generating the docs
module.exports = new Package('cli-docs', [basePackage, contentPackage])
module.exports =
new Package('cli-docs', [basePackage, contentPackage])

// Register the services and file readers
.factory(require('./readers/cli-command'))
// Register the services and file readers
.factory(require('./readers/cli-command'))

// Register the processors
.processor(require('./processors/processCliContainerDoc'))
.processor(require('./processors/processCliCommands'))
.processor(require('./processors/filterHiddenCommands'))
// Register the processors
.processor(require('./processors/processCliContainerDoc'))
.processor(require('./processors/processCliCommands'))
.processor(require('./processors/filterHiddenCommands'))

// Configure file reading
.config(function(readFilesProcessor, cliCommandFileReader) {
readFilesProcessor.fileReaders.push(cliCommandFileReader);
readFilesProcessor.sourceFiles = readFilesProcessor.sourceFiles.concat([
{
basePath: CLI_SOURCE_HELP_PATH,
include: resolve(CLI_SOURCE_HELP_PATH, '*.json'),
fileReader: 'cliCommandFileReader'
},
{
basePath: CONTENTS_PATH,
include: resolve(CONTENTS_PATH, 'cli/**'),
fileReader: 'contentFileReader'
},
]);
})
// Configure file reading
.config(function(readFilesProcessor, cliCommandFileReader) {
readFilesProcessor.fileReaders.push(cliCommandFileReader);
readFilesProcessor.sourceFiles = readFilesProcessor.sourceFiles.concat([
{
basePath: CLI_SOURCE_HELP_PATH,
include: resolve(CLI_SOURCE_HELP_PATH, '*.json'),
fileReader: 'cliCommandFileReader'
},
{
basePath: CONTENTS_PATH,
include: resolve(CONTENTS_PATH, 'cli/**'),
fileReader: 'contentFileReader'
},
]);
})

.config(function(templateFinder, templateEngine, getInjectables) {
// Where to find the templates for the CLI doc rendering
templateFinder.templateFolders.unshift(resolve(TEMPLATES_PATH, 'cli'));
// Add in templating filters and tags
templateEngine.filters = templateEngine.filters.concat(getInjectables(requireFolder(__dirname, './rendering')));
})
.config(function(templateFinder, templateEngine, getInjectables) {
// Where to find the templates for the CLI doc rendering
templateFinder.templateFolders.unshift(resolve(TEMPLATES_PATH, 'cli'));
// Add in templating filters and tags
templateEngine.filters = templateEngine.filters.concat(
getInjectables(requireFolder(__dirname, './rendering')));
})


.config(function(renderDocsProcessor) {
.config(function(renderDocsProcessor) {

const cliPackage = require(resolve(CLI_SOURCE_PATH, 'package.json'));
const repoUrlParts = cliPackage.repository.url.replace(/\.git$/, '').split('/');
const version = `v${cliPackage.version}`;
const repo = repoUrlParts.pop();
const owner = repoUrlParts.pop();
const cliVersionInfo = {
gitRepoInfo: { owner, repo },
currentVersion: { raw: version }
};
const cliPackage = require(resolve(CLI_SOURCE_PATH, 'package.json'));
const repoUrlParts = cliPackage.repository.url.replace(/\.git$/, '').split('/');
const version = `v${semver.clean(cliPackage.version)}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I don't think this is enough 😁
It generally works on branches, but doesn't seem to work on master. That is because cli-builds#master doesn't seem to be always be updated. For example, currently cli-builds#master > package.json >version is 8.0.0-beta.18+168.6ec0991, while cli-builds#8.0.x > package.json > version is 8.0.0+13.958d4cc 😞

Ideally, it should be fixed in the cli 😁
Or maybe we could always use master, when on angular/angular#master?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would we actually get the master build from cli-builds?
Don't we only install the version given by the build SHA. E.g.

    "extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 2bbd7f288",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. But that cli-builds SHA can come from cli-builds#master or cli-build#<some-branch>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this needs fixing in CLI: angular/angular-cli#14692

const repo = repoUrlParts.pop();
const owner = repoUrlParts.pop();
const cliVersionInfo = {gitRepoInfo: {owner, repo}, currentVersion: {raw: version}};

// Add the cli version data to the renderer, for use in things like github links
renderDocsProcessor.extraData.cliVersionInfo = cliVersionInfo;
})
// Add the cli version data to the renderer, for use in things like github links
renderDocsProcessor.extraData.cliVersionInfo = cliVersionInfo;
})


.config(function(convertToJsonProcessor, postProcessHtml) {
convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(['cli-command', 'cli-overview']);
postProcessHtml.docTypes = postProcessHtml.docTypes.concat(['cli-command', 'cli-overview']);
});
.config(function(convertToJsonProcessor, postProcessHtml) {
convertToJsonProcessor.docTypes =
convertToJsonProcessor.docTypes.concat(['cli-command', 'cli-overview']);
postProcessHtml.docTypes =
postProcessHtml.docTypes.concat(['cli-command', 'cli-overview']);
});
53 changes: 45 additions & 8 deletions aio/tools/transforms/cli-docs-package/readers/cli-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,59 @@ module.exports = function cliCommandFileReader(log) {
docType: 'cli-command',
id: `cli-${doc.name}`,
commandAliases: doc.aliases || [],
aliases: computeAliases(doc),
path,
aliases: computeAliases(doc), path,
outputPath: `${path}.json`,
breadCrumbs: [
{ text: 'CLI', path: 'cli' },
{ text: name, path },
{text: 'CLI', path: 'cli'},
{text: name, path},
]
});
if (doc.longDescription) {
doc.longDescriptionDoc = createLongDescriptionDoc(fileInfo);
}
return [result];
} catch (e) {
log.warn(`Failed to read cli command file: "${fileInfo.relativePath}" - ${e.message}`);
}
}
};
};
function computeAliases(doc) {
return [doc.name].concat(doc.aliases || []).map(alias => `cli-${alias}`);
}

/**
* Synthesize a doc for the CLI command long description, which is used to generate links
* for viewing and editing the long description in GitHub.
*
* The long description is stored in a markdown file that is referenced from the original
* schema file for the command, via the `$longDescription` field. The field is a relative path
* to the markdown file from the schema file.
*
* This function tries to retrieve that original schema based on the file path of the help JSON
* file, which was passed to the `cliCommandFileReader.getDocs()` method.
*/
function createLongDescriptionDoc(fileInfo) {
try {
const path = require('canonical-path');
const fs = require('fs');
const json5 = require('json5');

function computeAliases(doc) {
return [doc.name].concat(doc.aliases || []).map(alias => `cli-${alias}`);
}
const schemaJsonPath = path.resolve(fileInfo.basePath, '../commands', fileInfo.relativePath);
const schemaJson = fs.readFileSync(schemaJsonPath);
const schema = json5.parse(schemaJson);
if (schema.$longDescription) {
return {
docType: 'content',
startingLine: 0,
fileInfo: {
realProjectRelativePath:
path.join(path.dirname(fileInfo.realProjectRelativePath), schema.$longDescription)
}
};
}
} catch (e) {
log.warn('Unable to read CLI long description file info', e, fileInfo);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not fail hard here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided that not having a link for the description would be better than failing the build altogether. But perhaps you are right that we should fail so that it picks up on a breaking change to the layout of the CLI project.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a precedent for this further up the file in this FileReader where we catch similar errors and just log them as warnings... Perhaps that should be a hard fail too?

Copy link
Member

@gkalpak gkalpak Jun 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more hard fails the better 🎉
(Unless there are valid reasons for something to fail and be ignored 😁)

return undefined;
}
}
};
30 changes: 23 additions & 7 deletions aio/tools/transforms/cli-docs-package/readers/cli-command.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ const content = `
}
`;

const fileInfo = {content, baseName: 'add'};
const fileInfo = {
content,
baseName: 'add',
relativePath: 'add.json',
basePath: __dirname + '/mocks/help',
};

describe('cli-command reader', () => {
describe('getDocs', () => {
Expand Down Expand Up @@ -77,8 +82,8 @@ describe('cli-command reader', () => {
it('should compute the bread crumbs', () => {
const docs = reader.getDocs(fileInfo);
expect(docs[0].breadCrumbs).toEqual([
{ text: 'CLI', path: 'cli' },
{ text: 'add', path: 'cli/add' },
{text: 'CLI', path: 'cli'},
{text: 'add', path: 'cli/add'},
]);
});

Expand All @@ -89,7 +94,9 @@ describe('cli-command reader', () => {

it('should extract the long description', () => {
const docs = reader.getDocs(fileInfo);
expect(docs[0].longDescription).toEqual('Add support for a library in your project, for example adding `@angular/pwa` which would configure\nyour project for PWA support.\n');
expect(docs[0].longDescription)
.toEqual(
'Add support for a library in your project, for example adding `@angular/pwa` which would configure\nyour project for PWA support.\n');
});

it('should extract the command type', () => {
Expand All @@ -110,10 +117,19 @@ describe('cli-command reader', () => {
it('should extract the options', () => {
const docs = reader.getDocs(fileInfo);
expect(docs[0].options).toEqual([
jasmine.objectContaining({ name: 'collection' }),
jasmine.objectContaining({ name: 'help' }),
jasmine.objectContaining({ name: 'helpJson' }),
jasmine.objectContaining({name: 'collection'}),
jasmine.objectContaining({name: 'help'}),
jasmine.objectContaining({name: 'helpJson'}),
]);
});

it('should extract file info for the long description', () => {
const [doc] = reader.getDocs(fileInfo);
expect(doc.longDescriptionDoc).toEqual({
docType: 'content',
startingLine: 0,
fileInfo: {realProjectRelativePath: 'packages/angular/cli/commands/add-long.md'}
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"$longDescription": "./add-long.md"
}
5 changes: 4 additions & 1 deletion aio/tools/transforms/templates/cli/cli-command.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
{$ cli.renderSyntax(doc) $}

{% if doc.longDescription.length %}
<h2 class="no-anchor">Description</h2>
<h2 class="no-anchor">
{$ github.githubLinks(doc.longDescriptionDoc, cliVersionInfo) $}
Description
</h2>
{$ doc.longDescription | marked $}
{% endif%}

Expand Down