chore: add gulp link-checker task
also fix some of the broken links that it found
This commit is contained in:
parent
469612f50c
commit
1a154daa2e
|
@ -27,6 +27,4 @@ plnkr.html
|
|||
*plnkr.no-link.html
|
||||
public/docs/*/latest/guide/cheatsheet.json
|
||||
protractor-results.txt
|
||||
|
||||
|
||||
|
||||
link-checker-results.txt
|
||||
|
|
82
gulpfile.js
82
gulpfile.js
|
@ -23,6 +23,7 @@ var globby = require("globby");
|
|||
// Ugh... replacement needed to kill processes on any OS
|
||||
// - because childProcess.kill does not work properly on windows
|
||||
var treeKill = require("tree-kill");
|
||||
var blc = require("broken-link-checker");
|
||||
|
||||
// TODO:
|
||||
// 1. Think about using runSequence
|
||||
|
@ -424,6 +425,13 @@ gulp.task('test-api-builder', function (cb) {
|
|||
execCommands(['npm run test-api-builder'], {}, cb);
|
||||
});
|
||||
|
||||
// Usage:
|
||||
// angular.io: gulp link-checker
|
||||
// local site: gulp link-checker --url=http://localhost:3000
|
||||
gulp.task('link-checker', function(done) {
|
||||
return linkChecker();
|
||||
});
|
||||
|
||||
|
||||
// Internal tasks
|
||||
gulp.task('set-prod-env', function () {
|
||||
|
@ -514,6 +522,80 @@ function harpCompile() {
|
|||
return deferred.promise;
|
||||
}
|
||||
|
||||
function linkChecker(options) {
|
||||
var deferred = Q.defer();
|
||||
var options = options || {};
|
||||
|
||||
var blcOptions = options.blcOptions || {};
|
||||
var customData = options.customData || {};
|
||||
|
||||
var excludeBad; // don't bother reporting bad links matching this RegExp
|
||||
if (argv.excludeBad) {
|
||||
excludeBad = new RegExp(argv.excludeBad);
|
||||
} else {
|
||||
excludeBad = options.excludeBad === undefined ? /docs\/dart\/latest\/api/ : '';
|
||||
}
|
||||
|
||||
var previousPage;
|
||||
var siteUrl = argv.url || options.url || 'https://angular.io/';
|
||||
|
||||
// See https://github.com/stevenvachon/broken-link-checker#blcsitecheckeroptions-handlers
|
||||
var handlers = {
|
||||
robots: function(robots, customData){},
|
||||
html: function(tree, robots, response, pageUrl, customData){
|
||||
//gutil.log('Scanning ' + pageUrl);docs/ts/latest/api/core/
|
||||
},
|
||||
junk: function(result, customData){},
|
||||
|
||||
// Analyze links
|
||||
link: function(result, customData){
|
||||
if (!result.broken) { return; }
|
||||
if (excludeBad && excludeBad.test(result.url.resolved)) { return; }
|
||||
|
||||
var currentPage = result.base.resolved
|
||||
if (previousPage !== currentPage) {
|
||||
previousPage = currentPage;
|
||||
fs.appendFileSync(outputFile, '\n' + currentPage);
|
||||
gutil.log('broken: ' + currentPage);
|
||||
}
|
||||
var msg = '\n [' + result.html.location.line + ', ' + result.brokenReason + '] ' + result.url.resolved;
|
||||
fs.appendFileSync(outputFile, msg);
|
||||
//gutil.log(msg);
|
||||
//gutil.log(result);
|
||||
},
|
||||
|
||||
page: function(error, pageUrl, customData){},
|
||||
site: function(error, siteUrl, customData){},
|
||||
|
||||
end: function(){
|
||||
var stopTime = new Date().getTime();
|
||||
var elapsed = 'Elapsed link-checking time: ' + ((stopTime - startTime)/1000) + ' seconds';
|
||||
gutil.log(elapsed);
|
||||
fs.appendFileSync(outputFile, '\n'+elapsed);
|
||||
gutil.log('Output in file: ' + outputFile);
|
||||
deferred.resolve(true);
|
||||
}
|
||||
};
|
||||
|
||||
// create an output file with header.
|
||||
var outputFile = path.join(process.cwd(), 'link-checker-results.txt');
|
||||
var header = 'Link checker results for: ' + siteUrl +
|
||||
'\nStarted: ' + (new Date()).toLocaleString() +
|
||||
'\nSkipping bad links matching regex: ' +excludeBad.toString() + '\n\n';
|
||||
gutil.log(header);
|
||||
fs.writeFileSync(outputFile, header);
|
||||
|
||||
var siteChecker = new blc.SiteChecker(blcOptions, handlers);
|
||||
var startTime = new Date().getTime();
|
||||
|
||||
try {
|
||||
siteChecker.enqueue(siteUrl, customData);
|
||||
} catch (err) {
|
||||
deferred.reject(err);
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// harp has issues with node_modules under the public dir
|
||||
// but we need them there for example testing and development
|
||||
// this method allows the node modules folder under '_examples'
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
"devDependencies": {
|
||||
"archiver": "^0.16.0",
|
||||
"assert-plus": "^0.1.5",
|
||||
"broken-link-checker":"0.7.0",
|
||||
"browser-sync": "^2.9.3",
|
||||
"canonical-path": "0.0.2",
|
||||
"cross-spawn": "^2.1.0",
|
||||
|
|
|
@ -295,7 +295,7 @@ table(width="100%")
|
|||
In this example, the `table` element is removed from the DOM unless the `movies` array has a length.
|
||||
|
||||
The (*) before `ngIf` is required in this example.
|
||||
For more information see [Structural Directives](../guide/structural-directives).
|
||||
For more information see [Structural Directives](../guide/structural-directives.html).
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
|
@ -342,7 +342,7 @@ table(width="100%")
|
|||
the (#) identifies `movie` as a local variable;
|
||||
the list preposition is `of`, not `in`.
|
||||
|
||||
For more information see [Structural Directives](../guide/structural-directives).
|
||||
For more information see [Structural Directives](../guide/structural-directives.html).
|
||||
tr(style=top)
|
||||
td
|
||||
:marked
|
||||
|
|
|
@ -38,7 +38,7 @@ include ../_util-fns
|
|||
## Pass data from parent to child with input binding
|
||||
|
||||
`HeroChildComponent` has two ***input properties***,
|
||||
typically adorned with [@Input decorations](docs/ts/latest/guide/template-syntax.html#inputs-outputs).
|
||||
typically adorned with [@Input decorations](/docs/ts/latest/guide/template-syntax.html#inputs-outputs).
|
||||
|
||||
+makeExample('cb-component-communication/ts/app/hero-child.component.ts')
|
||||
:marked
|
||||
|
@ -142,7 +142,7 @@ figure.image-display
|
|||
The parent binds to that event property and reacts to those events.
|
||||
|
||||
The child's `EventEmitter` property is an ***output property***,
|
||||
typically adorned with an [@Output decoration](docs/ts/latest/guide/template-syntax.html#inputs-outputs)
|
||||
typically adorned with an [@Output decoration](/docs/ts/latest/guide/template-syntax.html#inputs-outputs)
|
||||
as seen in this `VoterComponent`:
|
||||
|
||||
+makeExample('cb-component-communication/ts/app/voter.component.ts')
|
||||
|
|
|
@ -403,7 +403,7 @@ figure
|
|||
Here's an example of a service class that logs to the browser console
|
||||
+makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (class only)')(format=".")
|
||||
:marked
|
||||
Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://www.html5rocks.com/en/tutorials/es6/promises/).
|
||||
Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://www.2ality.com/2014/10/es6-promises-api.html).
|
||||
The `HeroService` depends on the `LoggerService` and another `BackendService` that handles the server communication grunt work.
|
||||
+makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (class only)')(format=".")
|
||||
:marked
|
||||
|
|
|
@ -581,7 +581,7 @@ figure.image-display
|
|||
.l-sub-section
|
||||
:marked
|
||||
### The NgForm directive
|
||||
What `NgForm` directive? We didn't add an [NgForm](../api/core/NgForm-class.html) directive!
|
||||
What `NgForm` directive? We didn't add an [NgForm](../api/common/NgForm-directive.html) directive!
|
||||
|
||||
Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically.
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ figure.image-display
|
|||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Learn more about the `DatePipes` format options in the [API Docs](../api/core/DatePipe-class.html).
|
||||
Learn more about the `DatePipes` format options in the [API Docs](../api/common/DatePipe-class.html).
|
||||
:marked
|
||||
## Chaining pipes
|
||||
We can chain pipes together in potentially useful combinations.
|
||||
|
|
|
@ -895,7 +895,7 @@ code-example(format="").
|
|||
<a id="lifecycle-hooks"></a>
|
||||
### Router Lifecycle Hooks
|
||||
Angular components have [lifecycle hooks](lifecycle-hooks.html). For example, Angular calls the hook methods of the
|
||||
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy]((../api/core/OnDestroy-interface.html)
|
||||
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy](../api/core/OnDestroy-interface.html)
|
||||
interfaces when it creates and destroys components.
|
||||
|
||||
The router calls similar hook methods,
|
||||
|
@ -954,7 +954,7 @@ code-example(format="").
|
|||
:marked
|
||||
The `DialogService` (injected in the `AppComponent` for app-wide use) does the asking.
|
||||
|
||||
It returns a [promise](http://www.html5rocks.com/en/tutorials/es6/promises/) that
|
||||
It returns a [promise](http://www.2ality.com/2014/10/es6-promises-api.html) that
|
||||
*resolves* when the user eventually decides what to do: either
|
||||
to discard changes and navigate away (`true`) or to preserve the pending changes and stay in the crisis editor (`false`).
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2014-2016 Google, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
Loading…
Reference in New Issue