build(docs-infra): move docs-watch settings to a base package (#40479)

This new `base-authoring-package` captures all the settings, which
turns of potentially fatal checks, in one place. This new package is
then used as a base for all the docs-watch related packages, rather
than dotting the settings in a variety of different packages. This also
has the benefit that the standard configuration for doc-gen is fatal
on failed checks by default.

PR Close #40479
This commit is contained in:
Pete Bacon Darwin 2021-01-20 10:13:59 +00:00 committed by Jessica Janiuk
parent ead9ccd566
commit 9491318c26
12 changed files with 97 additions and 84 deletions

View File

@ -5,18 +5,22 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const { extname, resolve } = require('canonical-path');
const { existsSync } = require('fs');
const path = require('path');
const Package = require('dgeni').Package;
const Package = require('dgeni').Package;
const gitPackage = require('dgeni-packages/git');
const jsdocPackage = require('dgeni-packages/jsdoc');
const nunjucksPackage = require('dgeni-packages/nunjucks');
const linksPackage = require('../links-package');
const examplesPackage = require('../examples-package');
const targetPackage = require('../target-package');
const remarkPackage = require('../remark-package');
const postProcessPackage = require('dgeni-packages/post-process-html');
const { SRC_PATH } = require('../config');
const examplesPackage = require('../examples-package');
const linksPackage = require('../links-package');
const remarkPackage = require('../remark-package');
const targetPackage = require('../target-package');
const { PROJECT_ROOT, CONTENTS_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, TEMPLATES_PATH, AIO_PATH, requireFolder } = require('../config');
module.exports = new Package('angular-base', [
@ -53,13 +57,6 @@ module.exports = new Package('angular-base', [
inlineTagProcessor.inlineTagDefinitions.push(require('./inline-tag-defs/custom-search-defs/'));
})
.config(function(checkAnchorLinksProcessor, checkForUnusedExampleRegions) {
// These are disabled here to prevent false negatives for the `docs-watch` task.
// It is re-enabled in the main `angular.io-package`
checkAnchorLinksProcessor.$enabled = false;
checkForUnusedExampleRegions.$enabled = false;
})
// Where do we get the source files?
.config(function(readFilesProcessor, collectExamples, generateKeywordsProcessor, jsonFileReader) {
@ -125,7 +122,25 @@ module.exports = new Package('angular-base', [
getLinkInfo.useFirstAmbiguousLink = false;
})
.config(function(checkAnchorLinksProcessor) {
// since we encode the HTML to JSON we need to ensure that this processor runs before that encoding happens.
checkAnchorLinksProcessor.$runBefore = ['convertToJsonProcessor'];
checkAnchorLinksProcessor.$runAfter = ['fixInternalDocumentLinks'];
// We only want to check docs that are going to be output as JSON docs.
checkAnchorLinksProcessor.checkDoc = (doc) => doc.path && doc.outputPath && extname(doc.outputPath) === '.json' && doc.docType !== 'json-doc';
// Since we have a `base[href="/"]` arrangement all links are relative to that and not relative to the source document's path
checkAnchorLinksProcessor.base = '/';
// Ignore links to local assets
// (This is not optimal in terms of performance without making changes to dgeni-packages there is no other way.
// That being said do this only add 500ms onto the ~30sec doc-gen run - so not a huge issue)
checkAnchorLinksProcessor.ignoredLinks.push({
test(url) {
return (existsSync(resolve(SRC_PATH, url)));
}
});
checkAnchorLinksProcessor.pathVariants = ['', '/', '.html', '/index.html', '#top-of-page'];
checkAnchorLinksProcessor.errorOnUnmatchedLinks = true;
})
.config(function(computePathsProcessor, generateKeywordsProcessor) {

View File

@ -18,7 +18,7 @@ const { CONTENTS_PATH, GUIDE_EXAMPLES_PATH } = require('../config');
module.exports = new Package('angular-content', [basePackage, contentPackage])
// Where do we get the source files?
.config(function(readFilesProcessor, collectExamples, renderExamples) {
.config(function(readFilesProcessor, collectExamples) {
const gitignoreFilePath = path.resolve(GUIDE_EXAMPLES_PATH, '.gitignore');
const gitignoreFile = fs.readFileSync(gitignoreFilePath, 'utf8');
@ -91,8 +91,6 @@ module.exports = new Package('angular-content', [basePackage, contentPackage])
collectExamples.exampleFolders.push('examples');
collectExamples.registerIgnoredExamples(ignoredExamplePaths, gitignoreFilePath);
renderExamples.ignoreBrokenExamples = true;
})

View File

@ -11,9 +11,6 @@ const apiPackage = require('../angular-api-package');
const contentPackage = require('../angular-content-package');
const errorsPackage = require('../angular-errors-package');
const cliDocsPackage = require('../cli-docs-package');
const { extname, resolve } = require('canonical-path');
const { existsSync } = require('fs');
const { SRC_PATH } = require('../config');
module.exports = new Package('angular.io', [gitPackage, apiPackage, contentPackage, cliDocsPackage, errorsPackage])
@ -29,41 +26,6 @@ module.exports = new Package('angular.io', [gitPackage, apiPackage, contentPacka
renderDocsProcessor.extraData.versionInfo = versionInfo;
})
.config(function(checkForUnusedExampleRegions) {
// Re-enable this processor that was disabled in the `angular-base` package to
// avoid running it during `serve-and-sync` runs.
checkForUnusedExampleRegions.$enabled = true;
})
.config(function(checkAnchorLinksProcessor, linkInlineTagDef, renderExamples) {
// Fail the processing if there is an invalid link
linkInlineTagDef.failOnBadLink = true;
checkAnchorLinksProcessor.$enabled = true;
// since we encode the HTML to JSON we need to ensure that this processor runs before that encoding happens.
checkAnchorLinksProcessor.$runBefore = ['convertToJsonProcessor'];
checkAnchorLinksProcessor.$runAfter = ['fixInternalDocumentLinks'];
// We only want to check docs that are going to be output as JSON docs.
checkAnchorLinksProcessor.checkDoc = (doc) => doc.path && doc.outputPath && extname(doc.outputPath) === '.json' && doc.docType !== 'json-doc';
// Since we have a `base[href="/"]` arrangement all links are relative to that and not relative to the source document's path
checkAnchorLinksProcessor.base = '/';
// Ignore links to local assets
// (This is not optimal in terms of performance without making changes to dgeni-packages there is no other way.
// That being said do this only add 500ms onto the ~30sec doc-gen run - so not a huge issue)
checkAnchorLinksProcessor.ignoredLinks.push({
test(url) {
return (existsSync(resolve(SRC_PATH, url)));
}
});
checkAnchorLinksProcessor.pathVariants = ['', '/', '.html', '/index.html', '#top-of-page'];
checkAnchorLinksProcessor.errorOnUnmatchedLinks = true;
// Make sure we fail if the examples are not right
renderExamples.ignoreBrokenExamples = false;
})
.config(function(renderLinkInfo, postProcessHtml) {
renderLinkInfo.docTypes = postProcessHtml.docTypes;
});

View File

@ -8,6 +8,7 @@
const Package = require('dgeni').Package;
const apiPackage = require('../angular-api-package');
const { API_SOURCE_PATH } = require('../config');
const baseAuthoringPackage = require('./base-authoring-package');
const packageMap = {
animations: ['animations/index.ts', 'animations/browser/index.ts', 'animations/browser/testing/index.ts'],
@ -26,19 +27,19 @@ const packageMap = {
function createPackage(packageName) {
return new Package('author-api', [apiPackage])
.config(function(readTypeScriptModules) {
readTypeScriptModules.sourceFiles = packageMap[packageName];
})
.config(function(readFilesProcessor) {
readFilesProcessor.sourceFiles = [
{
basePath: API_SOURCE_PATH,
include: `${API_SOURCE_PATH}/examples/${packageName}/**/*`,
fileReader: 'exampleFileReader'
}
];
});
return new Package('author-api', [baseAuthoringPackage, apiPackage])
.config(function(readTypeScriptModules) {
readTypeScriptModules.sourceFiles = packageMap[packageName];
})
.config(function(readFilesProcessor) {
readFilesProcessor.sourceFiles = [
{
basePath: API_SOURCE_PATH,
include: `${API_SOURCE_PATH}/examples/${packageName}/**/*`,
fileReader: 'exampleFileReader'
}
];
});
}

View File

@ -0,0 +1,36 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const Package = require('dgeni').Package;
const basePackage = require('../angular-base-package');
/**
* A base package used by all the authoring packages in this folder.
*
* This package turns off lots of the potentially fatal checks to allow
* doc-gen to complete when authors are using the `docs-watch` or `serve-and-sync`
* jobs.
*/
const baseAuthoringPackage = new Package('base-authoring', [basePackage]);
baseAuthoringPackage
.config(function(checkAnchorLinksProcessor, checkForUnusedExampleRegions) {
// These are disabled here to prevent false negatives for the `docs-watch` task.
checkAnchorLinksProcessor.$enabled = false;
checkForUnusedExampleRegions.$enabled = false;
})
.config(function(linkInlineTagDef) {
// Do not fail the processing if there is an invalid link
linkInlineTagDef.failOnBadLink = false;
})
.config(function(renderExamples) {
// Do not fail the processing if there is a broken example
renderExamples.ignoreBrokenExamples = true;
});
module.exports = baseAuthoringPackage;

View File

@ -12,6 +12,7 @@ const {readFileSync} = require('fs');
const contentPackage = require('../angular-content-package');
const {CONTENTS_PATH} = require('../config');
const baseAuthoringPackage = require('./base-authoring-package');
const {codeExampleMatcher} = require('./utils');
/* eslint no-console: "off" */
@ -27,7 +28,7 @@ function createPackage(tutorialName) {
console.log(examples.map(example => ' - ' + example).join('\n'));
}
return new Package('author-getting-started', [contentPackage])
return new Package('author-getting-started', [baseAuthoringPackage, contentPackage])
.config(function(readFilesProcessor) {
readFilesProcessor.sourceFiles = [
{basePath: CONTENTS_PATH, include: tutorialFilePath, fileReader: 'contentFileReader'}, {

View File

@ -14,6 +14,7 @@ const {readFileSync} = require('fs');
const contentPackage = require('../angular-content-package');
const {CONTENTS_PATH} = require('../config');
const baseAuthoringPackage = require('./base-authoring-package');
const {codeExampleMatcher} = require('./utils');
function createPackage(guideName) {
@ -27,7 +28,7 @@ function createPackage(guideName) {
console.log(examples.map(example => ' - ' + example).join('\n'));
}
return new Package('author-guide', [contentPackage]).config(function(readFilesProcessor) {
return new Package('author-guide', [baseAuthoringPackage, contentPackage]).config(function(readFilesProcessor) {
readFilesProcessor.sourceFiles = [
{basePath: CONTENTS_PATH, include: guideFilePath, fileReader: 'contentFileReader'}, {
basePath: CONTENTS_PATH,

View File

@ -7,10 +7,11 @@
*/
const Package = require('dgeni').Package;
const contentPackage = require('../angular-content-package');
const { CONTENTS_PATH } = require('../config');
const {CONTENTS_PATH} = require('../config');
const baseAuthoringPackage = require('./base-authoring-package');
function createPackage() {
return new Package('author-marketing', [contentPackage])
return new Package('author-marketing', [baseAuthoringPackage, contentPackage])
.config(function(readFilesProcessor) {
readFilesProcessor.sourceFiles = [
{

View File

@ -12,6 +12,7 @@ const {readFileSync} = require('fs');
const contentPackage = require('../angular-content-package');
const {CONTENTS_PATH} = require('../config');
const baseAuthoringPackage = require('./base-authoring-package');
const {codeExampleMatcher} = require('./utils');
/* eslint no-console: "off" */
@ -27,7 +28,7 @@ function createPackage(tutorialName) {
console.log(examples.map(example => ' - ' + example).join('\n'));
}
return new Package('author-tutorial', [contentPackage]).config(function(readFilesProcessor) {
return new Package('author-tutorial', [baseAuthoringPackage, contentPackage]).config(function(readFilesProcessor) {
readFilesProcessor.sourceFiles = [
{basePath: CONTENTS_PATH, include: tutorialFilePath, fileReader: 'contentFileReader'}, {
basePath: CONTENTS_PATH,

View File

@ -29,15 +29,11 @@ if (process.argv.indexOf('--watch-only') === -1) {
console.log('Skip the full doc-gen by running: `yarn docs-watch --watch-only`');
console.log('================================================================');
const {Dgeni} = require('dgeni');
const dgeni = new Dgeni([require('../angular.io-package')]);
// Turn off all the potential failures for this doc-gen one-off run.
// This enables authors to run `docs-watch` while the docs are still in an unstable state.
const injector = dgeni.configureInjector();
injector.get('linkInlineTagDef').failOnBadLink = false;
injector.get('checkAnchorLinksProcessor').$enabled = false;
injector.get('renderExamples').ignoreBrokenExamples = true;
const dgeni = new Dgeni([
// The base-authoring-package will turn off potential failures for this doc-gen one-off run.
// This enables authors to run `docs-watch` while the docs are still in an unstable state.
require('./base-authoring-package'),
require('../angular.io-package')]);
p = dgeni.generate();
}

View File

@ -14,7 +14,7 @@ var INLINE_LINK = /(\S+)(?:\s+([\s\S]+))?/;
module.exports = function linkInlineTagDef(getLinkInfo, createDocMessage, log) {
return {
name: 'link',
failOnBadLink: false,
failOnBadLink: true,
description:
'Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors',
handler(doc, tagName, tagDescription) {

View File

@ -25,7 +25,7 @@ describe('link inline-tag-def', function() {
const doc = {};
const tagName = 'link';
const tagDescription = 'doc-id link text';
getLinkInfo.and.returnValue({ url: 'url/to/doc', title: 'link text' });
getLinkInfo.and.returnValue({ url: 'url/to/doc', title: 'link text', valid: true });
tag.handler(doc, tagName, tagDescription);
expect(getLinkInfo).toHaveBeenCalledWith('doc-id', 'link text', doc);
});
@ -34,7 +34,7 @@ describe('link inline-tag-def', function() {
const doc = {};
const tagName = 'link';
const tagDescription = 'doc-id link text';
getLinkInfo.and.returnValue({ url: 'url/to/doc', title: 'link text' });
getLinkInfo.and.returnValue({ url: 'url/to/doc', title: 'link text', valid: true });
const result = tag.handler(doc, tagName, tagDescription);
expect(result).toEqual('<a href=\'url/to/doc\'>link text</a>');
});
@ -43,6 +43,7 @@ describe('link inline-tag-def', function() {
const doc = {};
const tagName = 'link';
const tagDescription = 'doc-id link text';
tag.failOnBadLink = false;
getLinkInfo.and.returnValue({ valid: false, error: 'Error message', errorType: 'error' });
expect(() => tag.handler(doc, tagName, tagDescription)).not.toThrow();
expect(log.warn).toHaveBeenCalledWith('Error in {@link doc-id link text} - Error message - doc');