Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 1a154da

Browse files
committed
chore: add gulp link-checker task
also fix some of the broken links that it found
1 parent 469612f commit 1a154da

16 files changed

+114
-12
lines changed

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,4 @@ plnkr.html
2727
*plnkr.no-link.html
2828
public/docs/*/latest/guide/cheatsheet.json
2929
protractor-results.txt
30-
31-
32-
30+
link-checker-results.txt

gulpfile.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var globby = require("globby");
2323
// Ugh... replacement needed to kill processes on any OS
2424
// - because childProcess.kill does not work properly on windows
2525
var treeKill = require("tree-kill");
26+
var blc = require("broken-link-checker");
2627

2728
// TODO:
2829
// 1. Think about using runSequence
@@ -424,6 +425,13 @@ gulp.task('test-api-builder', function (cb) {
424425
execCommands(['npm run test-api-builder'], {}, cb);
425426
});
426427

428+
// Usage:
429+
// angular.io: gulp link-checker
430+
// local site: gulp link-checker --url=http://localhost:3000
431+
gulp.task('link-checker', function(done) {
432+
return linkChecker();
433+
});
434+
427435

428436
// Internal tasks
429437
gulp.task('set-prod-env', function () {
@@ -514,6 +522,80 @@ function harpCompile() {
514522
return deferred.promise;
515523
}
516524

525+
function linkChecker(options) {
526+
var deferred = Q.defer();
527+
var options = options || {};
528+
529+
var blcOptions = options.blcOptions || {};
530+
var customData = options.customData || {};
531+
532+
var excludeBad; // don't bother reporting bad links matching this RegExp
533+
if (argv.excludeBad) {
534+
excludeBad = new RegExp(argv.excludeBad);
535+
} else {
536+
excludeBad = options.excludeBad === undefined ? /docs\/dart\/latest\/api/ : '';
537+
}
538+
539+
var previousPage;
540+
var siteUrl = argv.url || options.url || 'https://angular.io/';
541+
542+
// See https://github.com/stevenvachon/broken-link-checker#blcsitecheckeroptions-handlers
543+
var handlers = {
544+
robots: function(robots, customData){},
545+
html: function(tree, robots, response, pageUrl, customData){
546+
//gutil.log('Scanning ' + pageUrl);docs/ts/latest/api/core/
547+
},
548+
junk: function(result, customData){},
549+
550+
// Analyze links
551+
link: function(result, customData){
552+
if (!result.broken) { return; }
553+
if (excludeBad && excludeBad.test(result.url.resolved)) { return; }
554+
555+
var currentPage = result.base.resolved
556+
if (previousPage !== currentPage) {
557+
previousPage = currentPage;
558+
fs.appendFileSync(outputFile, '\n' + currentPage);
559+
gutil.log('broken: ' + currentPage);
560+
}
561+
var msg = '\n [' + result.html.location.line + ', ' + result.brokenReason + '] ' + result.url.resolved;
562+
fs.appendFileSync(outputFile, msg);
563+
//gutil.log(msg);
564+
//gutil.log(result);
565+
},
566+
567+
page: function(error, pageUrl, customData){},
568+
site: function(error, siteUrl, customData){},
569+
570+
end: function(){
571+
var stopTime = new Date().getTime();
572+
var elapsed = 'Elapsed link-checking time: ' + ((stopTime - startTime)/1000) + ' seconds';
573+
gutil.log(elapsed);
574+
fs.appendFileSync(outputFile, '\n'+elapsed);
575+
gutil.log('Output in file: ' + outputFile);
576+
deferred.resolve(true);
577+
}
578+
};
579+
580+
// create an output file with header.
581+
var outputFile = path.join(process.cwd(), 'link-checker-results.txt');
582+
var header = 'Link checker results for: ' + siteUrl +
583+
'\nStarted: ' + (new Date()).toLocaleString() +
584+
'\nSkipping bad links matching regex: ' +excludeBad.toString() + '\n\n';
585+
gutil.log(header);
586+
fs.writeFileSync(outputFile, header);
587+
588+
var siteChecker = new blc.SiteChecker(blcOptions, handlers);
589+
var startTime = new Date().getTime();
590+
591+
try {
592+
siteChecker.enqueue(siteUrl, customData);
593+
} catch (err) {
594+
deferred.reject(err);
595+
}
596+
return deferred.promise;
597+
}
598+
517599
// harp has issues with node_modules under the public dir
518600
// but we need them there for example testing and development
519601
// this method allows the node modules folder under '_examples'

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"devDependencies": {
2929
"archiver": "^0.16.0",
3030
"assert-plus": "^0.1.5",
31+
"broken-link-checker":"0.7.0",
3132
"browser-sync": "^2.9.3",
3233
"canonical-path": "0.0.2",
3334
"cross-spawn": "^2.1.0",

public/docs/ts/latest/cookbook/a1-a2-quick-reference.jade

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ table(width="100%")
295295
In this example, the `table` element is removed from the DOM unless the `movies` array has a length.
296296

297297
The (*) before `ngIf` is required in this example.
298-
For more information see [Structural Directives](../guide/structural-directives).
298+
For more information see [Structural Directives](../guide/structural-directives.html).
299299
tr(style=top)
300300
td
301301
:marked
@@ -342,7 +342,7 @@ table(width="100%")
342342
the (#) identifies `movie` as a local variable;
343343
the list preposition is `of`, not `in`.
344344

345-
For more information see [Structural Directives](../guide/structural-directives).
345+
For more information see [Structural Directives](../guide/structural-directives.html).
346346
tr(style=top)
347347
td
348348
:marked

public/docs/ts/latest/cookbook/component-communication.jade

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ include ../_util-fns
3838
## Pass data from parent to child with input binding
3939

4040
`HeroChildComponent` has two ***input properties***,
41-
typically adorned with [@Input decorations](docs/ts/latest/guide/template-syntax.html#inputs-outputs).
41+
typically adorned with [@Input decorations](/docs/ts/latest/guide/template-syntax.html#inputs-outputs).
4242

4343
+makeExample('cb-component-communication/ts/app/hero-child.component.ts')
4444
:marked
@@ -142,7 +142,7 @@ figure.image-display
142142
The parent binds to that event property and reacts to those events.
143143

144144
The child's `EventEmitter` property is an ***output property***,
145-
typically adorned with an [@Output decoration](docs/ts/latest/guide/template-syntax.html#inputs-outputs)
145+
typically adorned with an [@Output decoration](/docs/ts/latest/guide/template-syntax.html#inputs-outputs)
146146
as seen in this `VoterComponent`:
147147

148148
+makeExample('cb-component-communication/ts/app/voter.component.ts')

public/docs/ts/latest/guide/architecture.jade

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ figure
403403
Here's an example of a service class that logs to the browser console
404404
+makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (class only)')(format=".")
405405
:marked
406-
Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://www.html5rocks.com/en/tutorials/es6/promises/).
406+
Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://www.2ality.com/2014/10/es6-promises-api.html).
407407
The `HeroService` depends on the `LoggerService` and another `BackendService` that handles the server communication grunt work.
408408
+makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (class only)')(format=".")
409409
:marked

public/docs/ts/latest/guide/forms.jade

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ figure.image-display
581581
.l-sub-section
582582
:marked
583583
### The NgForm directive
584-
What `NgForm` directive? We didn't add an [NgForm](../api/core/NgForm-class.html) directive!
584+
What `NgForm` directive? We didn't add an [NgForm](../api/common/NgForm-directive.html) directive!
585585

586586
Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically.
587587

public/docs/ts/latest/guide/pipes.jade

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ figure.image-display
8585

8686
.l-sub-section
8787
:marked
88-
Learn more about the `DatePipes` format options in the [API Docs](../api/core/DatePipe-class.html).
88+
Learn more about the `DatePipes` format options in the [API Docs](../api/common/DatePipe-class.html).
8989
:marked
9090
## Chaining pipes
9191
We can chain pipes together in potentially useful combinations.

public/docs/ts/latest/guide/router.jade

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ code-example(format="").
895895
<a id="lifecycle-hooks"></a>
896896
### Router Lifecycle Hooks
897897
Angular components have [lifecycle hooks](lifecycle-hooks.html). For example, Angular calls the hook methods of the
898-
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy]((../api/core/OnDestroy-interface.html)
898+
[OnInit](../api/core/OnInit-interface.html) and [OnDestroy](../api/core/OnDestroy-interface.html)
899899
interfaces when it creates and destroys components.
900900

901901
The router calls similar hook methods,
@@ -954,7 +954,7 @@ code-example(format="").
954954
:marked
955955
The `DialogService` (injected in the `AppComponent` for app-wide use) does the asking.
956956

957-
It returns a [promise](http://www.html5rocks.com/en/tutorials/es6/promises/) that
957+
It returns a [promise](http://www.2ality.com/2014/10/es6-promises-api.html) that
958958
*resolves* when the user eventually decides what to do: either
959959
to discard changes and navigate away (`true`) or to preserve the pending changes and stay in the crisis editor (`false`).
960960

public/license

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License
2+
3+
Copyright (c) 2014-2016 Google, Inc.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

0 commit comments

Comments
 (0)