Compare commits

..

2 Commits
5.2.8 ... 5.2.7

Author SHA1 Message Date
a10bf34471 docs: add changelog for 5.2.7 2018-02-28 15:01:38 -08:00
38146a2cd1 release: cut the 5.2.7 release 2018-02-28 15:00:20 -08:00
43 changed files with 225 additions and 518 deletions

View File

@ -41,14 +41,14 @@ jobs:
steps: steps:
- checkout: - checkout:
<<: *post_checkout <<: *post_checkout
# See remote cache documentation in /docs/BAZEL.md
- run: .circleci/setup_cache.sh
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
- *setup-bazel-remote-cache
# Check BUILD.bazel formatting before we have a node_modules directory - run: 'yarn buildifier -mode=check ||
# Then we don't need any exclude pattern to avoid checking those files (echo -e "\nBUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
- run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) || - run: 'yarn skylint ||
(echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
# Run the skylark linter to check our Bazel rules
- run: 'find . -type f -name "*.bzl" |
xargs java -jar /usr/local/bin/Skylint_deploy.jar ||
(echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)' (echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)'
- restore_cache: - restore_cache:

View File

@ -1,18 +1,3 @@
<a name="5.2.8"></a>
## [5.2.8](https://github.com/angular/angular/compare/5.2.7...5.2.8) (2018-03-07)
### Bug Fixes
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235)
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203)
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([789a47e](https://github.com/angular/angular/commit/789a47e)), closes [#10280](https://github.com/angular/angular/issues/10280)
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392)
* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390))
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175)
<a name="5.2.7"></a> <a name="5.2.7"></a>
## [5.2.7](https://github.com/angular/angular/compare/5.2.6...5.2.7) (2018-02-28) ## [5.2.7](https://github.com/angular/angular/compare/5.2.6...5.2.7) (2018-02-28)

View File

@ -1,10 +1,14 @@
workspace(name = "angular") workspace(name = "angular")
# Using a pre-release snapshot to pick up a commit that makes all nodejs_binary
# programs produce source-mapped stack traces.
RULES_NODEJS_VERSION = "926349cea4cd360afcd5647ccdd09d2d2fb471aa"
http_archive( http_archive(
name = "build_bazel_rules_nodejs", name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.0.zip", url = "https://github.com/bazelbuild/rules_nodejs/archive/%s.zip" % RULES_NODEJS_VERSION,
strip_prefix = "rules_nodejs-0.5.0", strip_prefix = "rules_nodejs-%s" % RULES_NODEJS_VERSION,
sha256 = "06aabb253c3867d51724386ac5622a0a238bbd82e2c70ce1d09ee3ceac4c31d6", sha256 = "5ba3c8c209078c2e3f0c6aa4abd01a1a561f92a5bfda04e25604af5f4734d69d",
) )
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories") load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
@ -12,11 +16,13 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_reposi
check_bazel_version("0.9.0") check_bazel_version("0.9.0")
node_repositories(package_json = ["//:package.json"]) node_repositories(package_json = ["//:package.json"])
RULES_TYPESCRIPT_VERSION = "d3cc5cd72d89aee0e4c2553ae1b99c707ecbef4e"
http_archive( http_archive(
name = "build_bazel_rules_typescript", name = "build_bazel_rules_typescript",
url = "https://github.com/bazelbuild/rules_typescript/archive/0.11.0.zip", url = "https://github.com/bazelbuild/rules_typescript/archive/%s.zip" % RULES_TYPESCRIPT_VERSION,
strip_prefix = "rules_typescript-0.11.0", strip_prefix = "rules_typescript-%s" % RULES_TYPESCRIPT_VERSION,
sha256 = "ce7bac7b5287d5162fcbe4f7c14ff507ae7d506ceb44626ad09f6b7e27d3260b", sha256 = "a233fcca41c3e59f639ac71c396edb30e9e9716cf8ed5fb20b51ff8910d5d895",
) )
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace") load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")

View File

@ -1,19 +1,20 @@
<!--The content below is only a placeholder and can be replaced.--> <!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center"> <div style="text-align:center">
<h1> <h1>
Welcome to {{ title }}! Welcome to {{title}}!!
</h1> </h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> <img width="300" alt="Angular logo" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
</div> </div>
<h2>Here are some links to help you start: </h2> <h2>Here are some links to help you start: </h2>
<ul> <ul>
<li> <li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2> <h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li> </li>
<li> <li>
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2> <h2><a target="_blank" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li> </li>
<li> <li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2> <h2><a target="_blank" href="http://angularjs.blogspot.ca/">Angular blog</a></h2>
</li> </li>
</ul> </ul>

View File

@ -1,5 +1,7 @@
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -18,13 +20,13 @@ describe('AppComponent', () => {
it(`should have as title 'app'`, async(() => { it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance; const app = fixture.debugElement.componentInstance;
expect(app.title).toMatch(/app/i); expect(app.title).toEqual('app');
})); }));
it('should render title in a h1 tag', async(() => { it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toMatch(/app/i); expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!');
})); }));
}); });

View File

@ -11,6 +11,6 @@ import { Component } from '@angular/core';
// #enddocregion metadata // #enddocregion metadata
// #docregion title, class // #docregion title, class
export class AppComponent { export class AppComponent {
title = 'My First Angular App!'; title = 'My First Angular App';
} }
// #enddocregion title, class // #enddocregion title, class

View File

@ -1,12 +1,12 @@
// #docregion // #docregion
import { Component, Input, OnInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core'; import { Component, Input, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core';
import { AdDirective } from './ad.directive'; import { AdDirective } from './ad.directive';
import { AdItem } from './ad-item'; import { AdItem } from './ad-item';
import { AdComponent } from './ad.component'; import { AdComponent } from './ad.component';
@Component({ @Component({
selector: 'app-ad-banner', selector: 'app-add-banner',
// #docregion ad-host // #docregion ad-host
template: ` template: `
<div class="ad-banner"> <div class="ad-banner">
@ -17,15 +17,16 @@ import { AdComponent } from './ad.component';
// #enddocregion ad-host // #enddocregion ad-host
}) })
// #docregion class // #docregion class
export class AdBannerComponent implements OnInit, OnDestroy { export class AdBannerComponent implements AfterViewInit, OnDestroy {
@Input() ads: AdItem[]; @Input() ads: AdItem[];
currentAdIndex: number = -1; currentAddIndex: number = -1;
@ViewChild(AdDirective) adHost: AdDirective; @ViewChild(AdDirective) adHost: AdDirective;
subscription: any;
interval: any; interval: any;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { } constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
ngOnInit() { ngAfterViewInit() {
this.loadComponent(); this.loadComponent();
this.getAds(); this.getAds();
} }
@ -35,8 +36,8 @@ export class AdBannerComponent implements OnInit, OnDestroy {
} }
loadComponent() { loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length; this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length;
let adItem = this.ads[this.currentAdIndex]; let adItem = this.ads[this.currentAddIndex];
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);

View File

@ -8,7 +8,7 @@ import { AdItem } from './ad-item';
selector: 'app-root', selector: 'app-root',
template: ` template: `
<div> <div>
<app-ad-banner [ads]="ads"></app-ad-banner> <app-add-banner [ads]="ads"></app-add-banner>
</div> </div>
` `
}) })

View File

@ -89,11 +89,11 @@ promise.then(() => {
The following code snippets illustrate how the same kind of operation is defined using observables and promises. The following code snippets illustrate how the same kind of operation is defined using observables and promises.
<table> <table>
<tr> <th>
<th>Operation</th> <td>Operation</td>
<th>Observable</th> <td>Observable</td>
<th>Promise</th> <td>Promise</td>
</tr> </th>
<tr> <tr>
<td>Creation</td> <td>Creation</td>
<td> <td>
@ -141,11 +141,10 @@ Using observables to handle events and asynchronous operations can have the adva
Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API. Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API.
<table> <table>
<tr> <th>
<th></th> <td>Observable</td>
<th>Observable</th> <td>Events API</td>
<th>Events API</th> </th>
</tr>
<tr> <tr>
<td>Creation & cancellation</td> <td>Creation & cancellation</td>
<td> <td>
@ -204,11 +203,10 @@ button.removeEventListener(click, handler);
An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery. An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery.
<table> <table>
<tr> <th>
<th></th> <td>Observable</td>
<th>Observable</th> <td>Array</td>
<th>Array</th> </th>
</tr>
<tr> <tr>
<td>Given</td> <td>Given</td>
<td> <td>

View File

@ -109,9 +109,9 @@ Take it step by step. First, it picks an ad.
The `loadComponent()` method chooses an ad using some math. The `loadComponent()` method chooses an ad using some math.
First, it sets the `currentAdIndex` by taking whatever it First, it sets the `currentAddIndex` by taking whatever it
currently is plus one, dividing that by the length of the `AdItem` array, and currently is plus one, dividing that by the length of the `AdItem` array, and
using the _remainder_ as the new `currentAdIndex` value. Then, it uses that using the _remainder_ as the new `currentAddIndex` value. Then, it uses that
value to select an `adItem` from the array. value to select an `adItem` from the array.

View File

@ -126,7 +126,7 @@ This is the _root component_ and it is named `app-root`.
You can find it in `./src/app/app.component.ts`. You can find it in `./src/app/app.component.ts`.
Open the component file and change the `title` property from `'app'` to `'My First Angular App!'`. Open the component file and change the `title` property from _Welcome to app!!_ to _Welcome to My First Angular App!!_:
<code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example> <code-example path="cli-quickstart/src/app/app.component.ts" region="title" title="src/app/app.component.ts" linenums="false"></code-example>

View File

@ -210,10 +210,10 @@ You can get runtime information about the current platform and the `appId` by in
#### Absolute HTTP URLs #### Absolute HTTP URLs
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data. The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `Http` module to fetch application data.
These services send requests to _relative_ URLs such as `api/heroes`. These services send requests to _relative_ URLs such as `api/heroes`.
In a Universal app, HTTP URLs must be _absolute_, for example, `https://my-server.com/api/heroes` In a Universal app, `Http` URLs must be _absolute_ (e.g., `https://my-server.com/api/heroes`)
even when the Universal web server is capable of handling those requests. even when the Universal web server is capable of handling those requests.
You'll have to change the services to make requests with absolute URLs when running on the server You'll have to change the services to make requests with absolute URLs when running on the server
@ -416,7 +416,7 @@ Create a `tsconfig.server.json` file in the project root directory to configure
This config extends from the root's `tsconfig.json` file. Certain settings are noteworthy for their differences. This config extends from the root's `tsconfig.json` file. Certain settings are noteworthy for their differences.
* The `module` property must be **commonjs** which can be required into our server application. * The `module` property must be **commonjs** which can be require()'d into our server application.
* The `angularCompilerOptions` section guides the AOT compiler: * The `angularCompilerOptions` section guides the AOT compiler:
* `entryModule` - the root module of the server application, expressed as `path/to/file#ClassName`. * `entryModule` - the root module of the server application, expressed as `path/to/file#ClassName`.

View File

@ -107,7 +107,7 @@
"cross-spawn": "^5.1.0", "cross-spawn": "^5.1.0",
"css-selector-parser": "^1.3.0", "css-selector-parser": "^1.3.0",
"dgeni": "^0.4.7", "dgeni": "^0.4.7",
"dgeni-packages": "^0.25.0", "dgeni-packages": "^0.24.0",
"entities": "^1.1.1", "entities": "^1.1.1",
"eslint": "^3.19.0", "eslint": "^3.19.0",
"eslint-plugin-jasmine": "^2.2.0", "eslint-plugin-jasmine": "^2.2.0",

View File

@ -131,6 +131,6 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
]); ]);
convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT); convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT);
postProcessHtml.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT); postProcessHtml.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT);
autoLinkCode.docTypes = DOCS_TO_CONVERT.concat(['member']); autoLinkCode.docTypes = DOCS_TO_CONVERT;
autoLinkCode.codeElements = ['code', 'code-example', 'code-pane']; autoLinkCode.codeElements = ['code', 'code-example', 'code-pane'];
}); });

View File

@ -5,21 +5,15 @@
*/ */
module.exports = function simplifyMemberAnchors() { module.exports = function simplifyMemberAnchors() {
return { return {
$runAfter: ['paths-computed'], $runAfter: ['extra-docs-added'],
$runBefore: ['rendering-docs'], $runBefore: ['computing-paths'],
$process: function(docs) { $process: function(docs) {
return docs.forEach(doc => { return docs.forEach(doc => {
if (doc.members) { if (doc.members) {
doc.members.forEach(member => { doc.members.forEach(member => member.anchor = computeAnchor(member));
member.anchor = computeAnchor(member);
member.path = doc.path + '#' + member.anchor;
});
} }
if (doc.statics) { if (doc.statics) {
doc.statics.forEach(member => { doc.statics.forEach(member => member.anchor = computeAnchor(member));
member.anchor = computeAnchor(member);
member.path = doc.path + '#' + member.anchor;
});
} }
}); });
} }

View File

@ -1,72 +0,0 @@
const testPackage = require('../../helpers/test-package');
const processorFactory = require('./simplifyMemberAnchors');
const Dgeni = require('dgeni');
describe('simplifyMemberAnchors processor', () => {
it('should be available on the injector', () => {
const dgeni = new Dgeni([testPackage('angular-api-package')]);
const injector = dgeni.configureInjector();
const processor = injector.get('simplifyMemberAnchors');
expect(processor.$process).toBeDefined();
expect(processor.$runAfter).toEqual(['paths-computed']);
expect(processor.$runBefore).toEqual(['rendering-docs']);
});
describe('$process', () => {
describe('docs without members', () => {
it('should ignore the docs', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc' },
{ id: 'some-other' }
];
processor.$process(docs);
expect(docs).toEqual([
{ id: 'some-doc' },
{ id: 'some-other' }
]);
});
});
describe('docs with members', () => {
it('should compute an anchor for each instance member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].members.map(member => member.anchor)).toEqual(['foo', 'new', 'call']);
});
it('should compute a path for each instance member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', path: 'a/b/c', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].members.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']);
});
});
describe('docs with static members', () => {
it('should compute an anchor for each static member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].statics.map(member => member.anchor)).toEqual(['foo', 'new', 'call']);
});
it('should compute a path for each static member', () => {
const processor = processorFactory();
const docs = [
{ id: 'some-doc', path: 'a/b/c', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }
];
processor.$process(docs);
expect(docs[0].statics.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']);
});
});
});
});

View File

@ -45,7 +45,7 @@ module.exports = function autoLinkCode(getDocFromAlias) {
parent.children.splice(index, 1, createLinkNode(docs[0], node.value)); parent.children.splice(index, 1, createLinkNode(docs[0], node.value));
} else { } else {
// Parse the text for words that we can convert to links // Parse the text for words that we can convert to links
const nodes = textContent(node).split(/([A-Za-z0-9_.-]+)/) const nodes = textContent(node).split(/([A-Za-z0-9_-]+)/)
.filter(word => word.length) .filter(word => word.length)
.map((word, index, words) => { .map((word, index, words) => {
// remove docs that fail the custom filter tests // remove docs that fail the custom filter tests

View File

@ -9,7 +9,7 @@ describe('autoLinkCode post-processor', () => {
const dgeni = new Dgeni([testPackage]); const dgeni = new Dgeni([testPackage]);
const injector = dgeni.configureInjector(); const injector = dgeni.configureInjector();
autoLinkCode = injector.get('autoLinkCode'); autoLinkCode = injector.get('autoLinkCode');
autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const', 'member']; autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const'];
aliasMap = injector.get('aliasMap'); aliasMap = injector.get('aliasMap');
processor = injector.get('postProcessHtml'); processor = injector.get('postProcessHtml');
processor.docTypes = ['test-doc']; processor.docTypes = ['test-doc'];
@ -31,13 +31,6 @@ describe('autoLinkCode post-processor', () => {
expect(doc.renderedContent).toEqual('<code><a href="a/b/myclass" class="code-anchor">foo.MyClass</a></code>'); expect(doc.renderedContent).toEqual('<code><a href="a/b/myclass" class="code-anchor">foo.MyClass</a></code>');
}); });
it('should match code items within a block of code that contain a dot in their identifier', () => {
aliasMap.addDoc({ docType: 'member', id: 'MyEnum.Value', aliases: ['Value', 'MyEnum.Value'], path: 'a/b/myenum' });
const doc = { docType: 'test-doc', renderedContent: '<code>someFn(): MyEnum.Value</code>' };
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code>someFn(): <a href="a/b/myenum" class="code-anchor">MyEnum.Value</a></code>');
});
it('should ignore code items that do not match a link to an API doc', () => { it('should ignore code items that do not match a link to an API doc', () => {
aliasMap.addDoc({ docType: 'guide', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' }); aliasMap.addDoc({ docType: 'guide', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });
const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' }; const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };

View File

@ -27,7 +27,6 @@ module.exports = function collectExamples(exampleMap, regionParser, log, createD
}, },
$process(docs) { $process(docs) {
const exampleFolders = this.exampleFolders; const exampleFolders = this.exampleFolders;
exampleFolders.forEach(folder => exampleMap[folder] = exampleMap[folder] || {});
const regionDocs = []; const regionDocs = [];
docs = docs.filter((doc) => { docs = docs.filter((doc) => {
if (doc.docType === 'example-file') { if (doc.docType === 'example-file') {
@ -37,6 +36,7 @@ module.exports = function collectExamples(exampleMap, regionParser, log, createD
if (doc.fileInfo.relativePath.indexOf(folder) === 0) { if (doc.fileInfo.relativePath.indexOf(folder) === 0) {
const relativePath = const relativePath =
doc.fileInfo.relativePath.substr(folder.length).replace(/^\//, ''); doc.fileInfo.relativePath.substr(folder.length).replace(/^\//, '');
exampleMap[folder] = exampleMap[folder] || {};
exampleMap[folder][relativePath] = doc; exampleMap[folder][relativePath] = doc;
// We treat files that end in `.annotated` specially // We treat files that end in `.annotated` specially

View File

@ -25,12 +25,6 @@ describe('collectExampleRegions processor', () => {
describe('$process', () => { describe('$process', () => {
it('should initialise the `exampleMap` even if there are no examples to collect', () => {
processor.$process([]);
expect(exampleMap['examples-1']).toEqual(jasmine.any(Object));
expect(exampleMap['examples-2']).toEqual(jasmine.any(Object));
});
it('should identify example files that are in the exampleFolders', () => { it('should identify example files that are in the exampleFolders', () => {
const docs = [ const docs = [
createDoc('A', 'examples-1/x/app.js'), createDoc('B', 'examples-1/y/index.html'), createDoc('A', 'examples-1/x/app.js'), createDoc('B', 'examples-1/y/index.html'),

View File

@ -8,16 +8,15 @@ module.exports =
.factory(require('./services/getAliases')) .factory(require('./services/getAliases'))
.factory(require('./services/getDocFromAlias')) .factory(require('./services/getDocFromAlias'))
.factory(require('./services/getLinkInfo')) .factory(require('./services/getLinkInfo'))
.factory(require('./services/disambiguators/disambiguateByDeprecated')) .factory(require('./services/moduleScopeLinkDisambiguator'))
.factory(require('./services/disambiguators/disambiguateByModule')) .factory(require('./services/deprecatedDocsLinkDisambiguator'))
.config(function(inlineTagProcessor, linkInlineTagDef) { .config(function(inlineTagProcessor, linkInlineTagDef) {
inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef); inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef);
}) })
.config(function(getDocFromAlias, disambiguateByDeprecated, disambiguateByModule) { .config(function(
getDocFromAlias.disambiguators = [ getLinkInfo, moduleScopeLinkDisambiguator, deprecatedDocsLinkDisambiguator) {
disambiguateByDeprecated, getLinkInfo.disambiguators.push(moduleScopeLinkDisambiguator);
disambiguateByModule getLinkInfo.disambiguators.push(deprecatedDocsLinkDisambiguator);
];
}); });

View File

@ -0,0 +1,12 @@
var _ = require('lodash');
module.exports = function deprecatedDocsLinkDisambiguator() {
return function(url, title, currentDoc, docs) {
if (docs.length != 2) return docs;
var filteredDocs = _.filter(
docs, function(doc) { return !doc.fileInfo.relativePath.match(/\/(\w+)-deprecated\//); });
return filteredDocs.length > 0 ? filteredDocs : docs;
};
};

View File

@ -1,3 +0,0 @@
module.exports = function disambiguateByDeprecated() {
return (alias, originatingDoc, docs) => docs.filter(doc => doc.deprecated === undefined);
};

View File

@ -1,17 +0,0 @@
const disambiguateByDeprecated = require('./disambiguateByDeprecated')();
const docs = [
{ id: 'doc1' },
{ id: 'doc2', deprecated: true },
{ id: 'doc3', deprecated: '' },
{ id: 'doc4' },
{ id: 'doc5', deprecated: 'Some text' },
];
describe('disambiguateByDeprecated', () => {
it('should filter out docs whose `deprecated` property is defined', () => {
expect(disambiguateByDeprecated('alias', {}, docs)).toEqual([
{ id: 'doc1' },
{ id: 'doc4' },
]);
});
});

View File

@ -1,12 +0,0 @@
module.exports = function disambiguateByModule() {
return (alias, originatingDoc, docs) => {
const originatingModule = originatingDoc && originatingDoc.moduleDoc;
if (originatingModule) {
const filteredDocs = docs.filter(doc => doc.moduleDoc === originatingModule);
if (filteredDocs.length > 0) {
return filteredDocs;
}
}
return docs;
};
};

View File

@ -1,29 +0,0 @@
const disambiguateByModule = require('./disambiguateByModule')();
const moduleA = { name: 'a' };
const moduleB = { name: 'b' };
const docs = [
{ id: 'doc1', moduleDoc: moduleA },
{ id: 'doc2', moduleDoc: moduleA },
{ id: 'doc3', moduleDoc: moduleB },
];
describe('disambiguateByModule', () => {
it('should return all docs if the originating doc has no moduleDoc', () => {
expect(disambiguateByModule('alias', { }, docs)).toEqual(docs);
});
it('should return all docs if no docs match the originating doc moduleDoc', () => {
expect(disambiguateByModule('alias', { moduleDoc: { name: 'c' } }, docs)).toEqual(docs);
});
it('should return only docs that match the moduleDoc of the originating doc', () => {
expect(disambiguateByModule('alias', { moduleDoc: moduleA }, docs)).toEqual([
{ id: 'doc1', moduleDoc: moduleA },
{ id: 'doc2', moduleDoc: moduleA },
]);
expect(disambiguateByModule('alias', { moduleDoc: moduleB }, docs)).toEqual([
{ id: 'doc3', moduleDoc: moduleB },
]);
});
});

View File

@ -1,23 +1,31 @@
var _ = require('lodash');
/** /**
* @dgService getDocFromAlias * @dgService getDocFromAlias
* @description Get an array of docs that match this alias, relative to the originating doc. * @description Get an array of docs that match this alias, relative to the originating doc.
*
* @property {Array<(alias: string, originatingDoc: Doc, ambiguousDocs: Doc[]) => Doc[]>} disambiguators
* a collection of functions that attempt to resolve ambiguous links. Each disambiguator returns
* a new collection of docs with unwanted ambiguous docs removed (see links-package/service/disambiguators
* for examples).
*/ */
module.exports = function getDocFromAlias(aliasMap) { module.exports = function getDocFromAlias(aliasMap) {
getDocFromAlias.disambiguators = []; return function getDocFromAlias(alias, originatingDoc) {
return getDocFromAlias; var docs = aliasMap.getDocs(alias);
function getDocFromAlias(alias, originatingDoc) { // If there is more than one item with this name then try to filter them by the originatingDoc's
return getDocFromAlias.disambiguators.reduce( // area
// Run the disambiguators while there is more than 1 doc found if (docs.length > 1 && originatingDoc && originatingDoc.area) {
(docs, disambiguater) => docs.length > 1 ? disambiguater(alias, originatingDoc, docs) : docs, docs = _.filter(docs, function(doc) { return doc.area === originatingDoc.area; });
// Start with the docs that match the alias }
aliasMap.getDocs(alias)
); // If filtering by area left us with none then let's start again
} if (docs.length === 0) {
docs = aliasMap.getDocs(alias);
}
// If there is more than one item with this name then try to filter them by the originatingDoc's
// module
if (docs.length > 1 && originatingDoc && originatingDoc.module) {
docs = _.filter(docs, function(doc) { return doc.module === originatingDoc.module; });
}
return docs;
};
}; };

View File

@ -3,15 +3,15 @@ var Dgeni = require('dgeni');
var getDocFromAlias, aliasMap; var getDocFromAlias, aliasMap;
describe('getDocFromAlias', () => { describe('getDocFromAlias', function() {
beforeEach(() => { beforeEach(function() {
var dgeni = new Dgeni([testPackage('links-package', true)]); var dgeni = new Dgeni([testPackage('links-package', true)]);
var injector = dgeni.configureInjector(); var injector = dgeni.configureInjector();
aliasMap = injector.get('aliasMap'); aliasMap = injector.get('aliasMap');
getDocFromAlias = injector.get('getDocFromAlias'); getDocFromAlias = injector.get('getDocFromAlias');
}); });
it('should return an array of docs that match the alias', () => { it('should return an array of docs that match the alias', function() {
var doc1 = {aliases: ['a', 'b', 'c']}; var doc1 = {aliases: ['a', 'b', 'c']};
var doc2 = {aliases: ['a', 'b']}; var doc2 = {aliases: ['a', 'b']};
var doc3 = {aliases: ['a']}; var doc3 = {aliases: ['a']};
@ -24,24 +24,25 @@ describe('getDocFromAlias', () => {
expect(getDocFromAlias('c')).toEqual([doc1]); expect(getDocFromAlias('c')).toEqual([doc1]);
}); });
it('should filter ambiguous docs by calling each disambiguator', () => { it('should return docs that match the alias and originating doc\'s area', function() {
getDocFromAlias.disambiguators = [ var doc1 = {aliases: ['a'], area: 'api'};
(alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('X') !== -1), // only if X appears in name var doc2 = {aliases: ['a'], area: 'api'};
(alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('Y') !== -1) // only if Y appears in name var doc3 = {aliases: ['a'], area: 'other'};
];
var doc1 = {name: 'X', aliases: ['a', 'b', 'c']};
var doc2 = {name: 'Y', aliases: ['a', 'b']};
var doc3 = {name: 'XY', aliases: ['a', 'c']};
aliasMap.addDoc(doc1); aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2); aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3); aliasMap.addDoc(doc3);
// doc1 and doc2 get removed as they don't both have X and Y in name expect(getDocFromAlias('a', {area: 'api'})).toEqual([doc1, doc2]);
expect(getDocFromAlias('a')).toEqual([doc3]); });
// doc2 gets removed as it has no X; then we have only one doc left so second disambiguator never runs
expect(getDocFromAlias('b')).toEqual([doc1]); it('should return docs that match the alias and originating doc\'s area and module', function() {
// doc1 gets removed as it has no Y; then we have only one doc left (which would anyway pass 2nd disambiguator) var doc1 = {aliases: ['a'], area: 'api', module: 'ng'};
expect(getDocFromAlias('c')).toEqual([doc3]); var doc2 = {aliases: ['a'], area: 'api', module: 'ngMock'};
var doc3 = {aliases: ['a'], area: 'other', module: 'ng'};
aliasMap.addDoc(doc1);
aliasMap.addDoc(doc2);
aliasMap.addDoc(doc3);
expect(getDocFromAlias('a', {area: 'api', module: 'ng'})).toEqual([doc1]);
}); });
}); });

View File

@ -10,9 +10,14 @@ var path = require('canonical-path');
* @return {Object} The link information * @return {Object} The link information
* *
* @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc * @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc
* @property {array<function(url, title, currentDoc, ambiguousDocs) : array} disambiguators a collection of functions
* that attempt to resolve ambiguous links. Each disambiguator returns a new collection of docs with
* unwanted ambiguous docs removed (see moduleScopeLinkDisambiguator service for an example).
*/ */
module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) { module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {
getLinkInfoImpl.disambiguators = [];
return getLinkInfoImpl; return getLinkInfoImpl;
function getLinkInfoImpl(url, title, currentDoc) { function getLinkInfoImpl(url, title, currentDoc) {
@ -24,6 +29,11 @@ module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {
var docs = getDocFromAlias(url, currentDoc); var docs = getDocFromAlias(url, currentDoc);
// Give each disambiguator a chance to reduce the number of ambiguous docs
docs = getLinkInfoImpl.disambiguators.reduce(function(docs, disambiguator) {
return disambiguator(url, title, currentDoc, docs);
}, docs);
if (!getLinkInfoImpl.useFirstAmbiguousLink && docs.length > 1) { if (!getLinkInfoImpl.useFirstAmbiguousLink && docs.length > 1) {
linkInfo.valid = false; linkInfo.valid = false;
linkInfo.errorType = 'ambiguous'; linkInfo.errorType = 'ambiguous';
@ -70,4 +80,5 @@ module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {
return linkInfo; return linkInfo;
} }
}; };

View File

@ -0,0 +1,15 @@
var _ = require('lodash');
module.exports = function moduleScopeLinkDisambiguator() {
return function(url, title, currentDoc, docs) {
if (docs.length > 1) {
// filter out target docs that are not in the same module as the source doc
var filteredDocs =
_.filter(docs, function(doc) { return doc.moduleDoc === currentDoc.moduleDoc; });
// if all target docs are in a different module then just return the full collection of
// ambiguous docs
return filteredDocs.length > 0 ? filteredDocs : docs;
}
return docs;
};
};

View File

@ -2312,9 +2312,9 @@ devtools-timeline-model@1.1.6:
chrome-devtools-frontend "1.0.401423" chrome-devtools-frontend "1.0.401423"
resolve "1.1.7" resolve "1.1.7"
dgeni-packages@^0.25.0: dgeni-packages@^0.24.0:
version "0.25.0" version "0.24.0"
resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.25.0.tgz#380f0b569ae36d82959252604b729e85e0cd7d4a" resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.24.0.tgz#2f995f78fecd6a9ded72d7bdccbbc4c46360c1ea"
dependencies: dependencies:
canonical-path "0.0.2" canonical-path "0.0.2"
catharsis "^0.8.1" catharsis "^0.8.1"

View File

@ -40,14 +40,13 @@ Week Of | Stable Release<br>(@latest npm tag) | Beta/RC Release<br>(@n
2018-02-14   | 5.2.5                               | 6.0.0beta.4                       | 2018-02-14   | 5.2.5                               | 6.0.0beta.4                       |
2018-02-21   | 5.2.6                               | 6.0.0beta.5                       | 2018-02-21   | 5.2.6                               | 6.0.0beta.5                       |
2018-02-28   | 5.2.7                               | 6.0.0beta.6                       | 2018-02-28   | 5.2.7                               | 6.0.0beta.6                       |
2018-03-07   | 5.2.8                               | 6.0.0beta.7                       | 2018-03-07   | 5.2.8                               | 6.0.0rc.0                         |
2018-03-14   | 5.2.9                               | 6.0.0rc.0                         | 2018-03-14   | 5.2.9                               | 6.0.0rc.1                         |
2018-03-21   | 5.2.10                              | 6.0.0rc.1                         | 2018-03-21   | 5.2.10                              | 6.0.0rc.2                         |
2018-03-28   | 5.2.11                              | 6.0.0rc.2                         | 2018-03-28   | 6.0.0                               | -                                  | Major Release
2018-04-04   | 6.0.0                               | -                                  | Major Release 2018-04-04   | 6.0.1                               | -                                  |
2018-04-11   | 6.0.1                               | -                                  | 2018-04-11   | 6.0.2                               | -                                  |
2018-04-18   | 6.0.2                               | -                                  | [ng-conf](https://www.ng-conf.org/) 2018-04-18   | -                                   | -                                  | [ng-conf](https://www.ng-conf.org/)
## Tentative Schedule After April 2018 ## Tentative Schedule After April 2018

View File

@ -1,20 +1,28 @@
workspace(name = "bazel_integration_test") workspace(name = "bazel_integration_test")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
# Using a pre-release snapshot to pick up a commit that makes all nodejs_binary
# programs produce source-mapped stack traces.
RULES_NODEJS_VERSION = "926349cea4cd360afcd5647ccdd09d2d2fb471aa"
http_archive( http_archive(
name = "build_bazel_rules_nodejs", name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.0.zip", url = "https://github.com/bazelbuild/rules_nodejs/archive/%s.zip" % RULES_NODEJS_VERSION,
strip_prefix = "rules_nodejs-0.5.0", strip_prefix = "rules_nodejs-%s" % RULES_NODEJS_VERSION,
sha256 = "06aabb253c3867d51724386ac5622a0a238bbd82e2c70ce1d09ee3ceac4c31d6", sha256 = "5ba3c8c209078c2e3f0c6aa4abd01a1a561f92a5bfda04e25604af5f4734d69d",
) )
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories") load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
node_repositories(package_json = ["//:package.json"]) node_repositories(package_json = ["//:package.json"])
RULES_TYPESCRIPT_VERSION = "d3cc5cd72d89aee0e4c2553ae1b99c707ecbef4e"
http_archive( http_archive(
name = "build_bazel_rules_typescript", name = "build_bazel_rules_typescript",
url = "https://github.com/bazelbuild/rules_typescript/archive/0.11.0.zip", url = "https://github.com/bazelbuild/rules_typescript/archive/%s.zip" % RULES_TYPESCRIPT_VERSION,
strip_prefix = "rules_typescript-0.11.0", strip_prefix = "rules_typescript-%s" % RULES_TYPESCRIPT_VERSION,
sha256 = "ce7bac7b5287d5162fcbe4f7c14ff507ae7d506ceb44626ad09f6b7e27d3260b", sha256 = "a233fcca41c3e59f639ac71c396edb30e9e9716cf8ed5fb20b51ff8910d5d895",
) )
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace") load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")

View File

@ -1,6 +1,6 @@
{ {
"name": "angular-srcs", "name": "angular-srcs",
"version": "5.2.8", "version": "5.2.7",
"private": true, "private": true,
"branchPattern": "2.0.*", "branchPattern": "2.0.*",
"description": "Angular - a web framework for modern web apps", "description": "Angular - a web framework for modern web apps",
@ -99,7 +99,7 @@
"source-map": "0.5.7", "source-map": "0.5.7",
"source-map-support": "0.4.18", "source-map-support": "0.4.18",
"systemjs": "0.18.10", "systemjs": "0.18.10",
"ts-api-guardian": "^0.3.0", "ts-api-guardian": "0.2.2",
"tsickle": "0.26.0", "tsickle": "0.26.0",
"tslint": "5.7.0", "tslint": "5.7.0",
"tslint-eslint-rules": "4.1.1", "tslint-eslint-rules": "4.1.1",

View File

@ -113,7 +113,7 @@ esm5_outputs_aspect = aspect(
# For some reason, having the compiler output as an input to the action above # For some reason, having the compiler output as an input to the action above
# is not sufficient. # is not sufficient.
"_tsc_wrapped": attr.label( "_tsc_wrapped": attr.label(
default = Label("@build_bazel_rules_typescript//internal:tsc_wrapped_bin"), default = Label("@build_bazel_rules_typescript//internal/tsc_wrapped:tsc_wrapped_bin"),
executable = True, executable = True,
cfg = "host", cfg = "host",
), ),

View File

@ -16,7 +16,7 @@ ts_library(
# Users will get this dependency from node_modules. # Users will get this dependency from node_modules.
"//packages/compiler-cli", "//packages/compiler-cli",
# END-INTERNAL # END-INTERNAL
"@build_bazel_rules_typescript//internal:tsc_wrapped", "@build_bazel_rules_typescript//internal/tsc_wrapped",
], ],
) )

View File

@ -95,13 +95,6 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true,
}): {diagnostics: ng.Diagnostics, program: ng.Program} { }): {diagnostics: ng.Diagnostics, program: ng.Program} {
let fileLoader: FileLoader; let fileLoader: FileLoader;
if (bazelOpts.maxCacheSizeMb !== undefined) {
const maxCacheSizeBytes = bazelOpts.maxCacheSizeMb * (1 << 20);
fileCache.setMaxCacheSize(maxCacheSizeBytes);
} else {
fileCache.resetMaxCacheSize();
}
if (inputs) { if (inputs) {
fileLoader = new CachedFileLoader(fileCache, allowNonHermeticReads); fileLoader = new CachedFileLoader(fileCache, allowNonHermeticReads);
// Resolve the inputs to absolute paths to match TypeScript internals // Resolve the inputs to absolute paths to match TypeScript internals

View File

@ -280,7 +280,7 @@ export class DefaultUrlSerializer implements UrlSerializer {
serialize(tree: UrlTree): string { serialize(tree: UrlTree): string {
const segment = `/${serializeSegment(tree.root, true)}`; const segment = `/${serializeSegment(tree.root, true)}`;
const query = serializeQueryParams(tree.queryParams); const query = serializeQueryParams(tree.queryParams);
const fragment = typeof tree.fragment === `string` ? `#${encodeUriQuery(tree.fragment !)}` : ''; const fragment = typeof tree.fragment === `string` ? `#${encodeURI(tree.fragment !)}` : '';
return `${segment}${query}${fragment}`; return `${segment}${query}${fragment}`;
} }
@ -326,10 +326,9 @@ function serializeSegment(segment: UrlSegmentGroup, root: boolean): string {
} }
/** /**
* Encodes a URI string with the default encoding. This function will only ever be called from * This method is intended for encoding *key* or *value* parts of query component. We need a custom
* `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
* a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't * encoded per http://tools.ietf.org/html/rfc3986:
* have to be encoded per http://tools.ietf.org/html/rfc3986:
* query = *( pchar / "/" / "?" ) * query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@" * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
@ -337,61 +336,32 @@ function serializeSegment(segment: UrlSegmentGroup, root: boolean): string {
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "=" * / "*" / "+" / "," / ";" / "="
*/ */
function encodeUriString(s: string): string { export function encode(s: string): string {
return encodeURIComponent(s) return encodeURIComponent(s)
.replace(/%40/g, '@') .replace(/%40/g, '@')
.replace(/%3A/gi, ':') .replace(/%3A/gi, ':')
.replace(/%24/g, '$') .replace(/%24/g, '$')
.replace(/%2C/gi, ','); .replace(/%2C/gi, ',')
} .replace(/%3B/gi, ';');
/**
* This function should be used to encode both keys and values in a query string key/value or the
* URL fragment. In the following URL, you need to call encodeUriQuery on "k", "v" and "f":
*
* http://www.site.org/html;mk=mv?k=v#f
*/
export function encodeUriQuery(s: string): string {
return encodeUriString(s).replace(/%3B/gi, ';');
}
/**
* This function should be run on any URI segment as well as the key and value in a key/value
* pair for matrix params. In the following URL, you need to call encodeUriSegment on "html",
* "mk", and "mv":
*
* http://www.site.org/html;mk=mv?k=v#f
*/
export function encodeUriSegment(s: string): string {
return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&');
} }
export function decode(s: string): string { export function decode(s: string): string {
return decodeURIComponent(s); return decodeURIComponent(s);
} }
// Query keys/values should have the "+" replaced first, as "+" in a query string is " ".
// decodeURIComponent function will not decode "+" as a space.
export function decodeQuery(s: string): string {
return decode(s.replace(/\+/g, '%20'));
}
export function serializePath(path: UrlSegment): string { export function serializePath(path: UrlSegment): string {
return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`; return `${encode(path.path)}${serializeParams(path.parameters)}`;
} }
function serializeMatrixParams(params: {[key: string]: string}): string { function serializeParams(params: {[key: string]: string}): string {
return Object.keys(params) return Object.keys(params).map(key => `;${encode(key)}=${encode(params[key])}`).join('');
.map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`)
.join('');
} }
function serializeQueryParams(params: {[key: string]: any}): string { function serializeQueryParams(params: {[key: string]: any}): string {
const strParams: string[] = Object.keys(params).map((name) => { const strParams: string[] = Object.keys(params).map((name) => {
const value = params[name]; const value = params[name];
return Array.isArray(value) ? return Array.isArray(value) ? value.map(v => `${encode(name)}=${encode(v)}`).join('&') :
value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : `${encode(name)}=${encode(value)}`;
`${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
}); });
return strParams.length ? `?${strParams.join("&")}` : ''; return strParams.length ? `?${strParams.join("&")}` : '';
@ -444,7 +414,7 @@ class UrlParser {
} }
parseFragment(): string|null { parseFragment(): string|null {
return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null; return this.consumeOptional('#') ? decodeURI(this.remaining) : null;
} }
private parseChildren(): {[outlet: string]: UrlSegmentGroup} { private parseChildren(): {[outlet: string]: UrlSegmentGroup} {
@ -536,8 +506,8 @@ class UrlParser {
} }
} }
const decodedKey = decodeQuery(key); const decodedKey = decode(key);
const decodedVal = decodeQuery(value); const decodedVal = decode(value);
if (params.hasOwnProperty(decodedKey)) { if (params.hasOwnProperty(decodedKey)) {
// Append to existing values // Append to existing values

View File

@ -7,7 +7,7 @@
*/ */
import {PRIMARY_OUTLET} from '../src/shared'; import {PRIMARY_OUTLET} from '../src/shared';
import {DefaultUrlSerializer, UrlSegmentGroup, encodeUriQuery, encodeUriSegment, serializePath} from '../src/url_tree'; import {DefaultUrlSerializer, UrlSegmentGroup, encode, serializePath} from '../src/url_tree';
describe('url serializer', () => { describe('url serializer', () => {
const url = new DefaultUrlSerializer(); const url = new DefaultUrlSerializer();
@ -189,7 +189,7 @@ describe('url serializer', () => {
describe('encoding/decoding', () => { describe('encoding/decoding', () => {
it('should encode/decode path segments and parameters', () => { it('should encode/decode path segments and parameters', () => {
const u = const u =
`/${encodeUriSegment("one two")};${encodeUriSegment("p 1")}=${encodeUriSegment("v 1")};${encodeUriSegment("p 2")}=${encodeUriSegment("v 2")}`; `/${encode("one two")};${encode("p 1")}=${encode("v 1")};${encode("p 2")}=${encode("v 2")}`;
const tree = url.parse(u); const tree = url.parse(u);
expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one two'); expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one two');
@ -199,8 +199,7 @@ describe('url serializer', () => {
}); });
it('should encode/decode "slash" in path segments and parameters', () => { it('should encode/decode "slash" in path segments and parameters', () => {
const u = const u = `/${encode("one/two")};${encode("p/1")}=${encode("v/1")}/three`;
`/${encodeUriSegment("one/two")};${encodeUriSegment("p/1")}=${encodeUriSegment("v/1")}/three`;
const tree = url.parse(u); const tree = url.parse(u);
const segment = tree.root.children[PRIMARY_OUTLET].segments[0]; const segment = tree.root.children[PRIMARY_OUTLET].segments[0];
expect(segment.path).toEqual('one/two'); expect(segment.path).toEqual('one/two');
@ -211,8 +210,7 @@ describe('url serializer', () => {
}); });
it('should encode/decode query params', () => { it('should encode/decode query params', () => {
const u = const u = `/one?${encode("p 1")}=${encode("v 1")}&${encode("p 2")}=${encode("v 2")}`;
`/one?${encodeUriQuery("p 1")}=${encodeUriQuery("v 1")}&${encodeUriQuery("p 2")}=${encodeUriQuery("v 2")}`;
const tree = url.parse(u); const tree = url.parse(u);
expect(tree.queryParams).toEqual({'p 1': 'v 1', 'p 2': 'v 2'}); expect(tree.queryParams).toEqual({'p 1': 'v 1', 'p 2': 'v 2'});
@ -221,143 +219,28 @@ describe('url serializer', () => {
expect(url.serialize(tree)).toEqual(u); expect(url.serialize(tree)).toEqual(u);
}); });
it('should decode spaces in query as %20 or +', () => {
const u1 = `/one?foo=bar baz`;
const u2 = `/one?foo=bar+baz`;
const u3 = `/one?foo=bar%20baz`;
const u1p = url.parse(u1);
const u2p = url.parse(u2);
const u3p = url.parse(u3);
expect(url.serialize(u1p)).toBe(url.serialize(u2p));
expect(url.serialize(u2p)).toBe(url.serialize(u3p));
expect(u1p.queryParamMap.get('foo')).toBe('bar baz');
expect(u2p.queryParamMap.get('foo')).toBe('bar baz');
expect(u3p.queryParamMap.get('foo')).toBe('bar baz');
});
it('should encode query params leaving sub-delimiters intact', () => { it('should encode query params leaving sub-delimiters intact', () => {
const percentChars = '/?#&+=[] '; const percentChars = '/?#[]&+= ';
const percentCharsEncoded = '%2F%3F%23%26%2B%3D%5B%5D%20'; const percentCharsEncoded = '%2F%3F%23%5B%5D%26%2B%3D%20';
const intactChars = '!$\'()*,;:'; const intactChars = '!$\'()*,;:';
const params = percentChars + intactChars; const params = percentChars + intactChars;
const paramsEncoded = percentCharsEncoded + intactChars; const paramsEncoded = percentCharsEncoded + intactChars;
const mixedCaseString = 'sTrInG'; const mixedCaseString = 'sTrInG';
expect(percentCharsEncoded).toEqual(encodeUriQuery(percentChars)); expect(percentCharsEncoded).toEqual(encode(percentChars));
expect(intactChars).toEqual(encodeUriQuery(intactChars)); expect(intactChars).toEqual(encode(intactChars));
// Verify it replaces repeated characters correctly // Verify it replaces repeated characters correctly
expect(paramsEncoded + paramsEncoded).toEqual(encodeUriQuery(params + params)); expect(paramsEncoded + paramsEncoded).toEqual(encode(params + params));
// Verify it doesn't change the case of alpha characters // Verify it doesn't change the case of alpha characters
expect(mixedCaseString + paramsEncoded).toEqual(encodeUriQuery(mixedCaseString + params)); expect(mixedCaseString + paramsEncoded).toEqual(encode(mixedCaseString + params));
}); });
it('should encode/decode fragment', () => { it('should encode/decode fragment', () => {
const u = `/one#${encodeUriQuery('one two=three four')}`; const u = `/one#${encodeURI("one two=three four")}`;
const tree = url.parse(u); const tree = url.parse(u);
expect(tree.fragment).toEqual('one two=three four'); expect(tree.fragment).toEqual('one two=three four');
expect(url.serialize(tree)).toEqual('/one#one%20two%3Dthree%20four'); expect(url.serialize(tree)).toEqual(u);
});
});
describe('special character encoding/decoding', () => {
// Tests specific to https://github.com/angular/angular/issues/10280
it('should parse encoded parens in matrix params', () => {
const auxRoutesUrl = '/abc;foo=(other:val)';
const fooValueUrl = '/abc;foo=%28other:val%29';
const auxParsed = url.parse(auxRoutesUrl).root;
const fooParsed = url.parse(fooValueUrl).root;
// Test base case
expect(auxParsed.children[PRIMARY_OUTLET].segments.length).toBe(1);
expect(auxParsed.children[PRIMARY_OUTLET].segments[0].path).toBe('abc');
expect(auxParsed.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({foo: ''});
expect(auxParsed.children['other'].segments.length).toBe(1);
expect(auxParsed.children['other'].segments[0].path).toBe('val');
// Confirm matrix params are URL decoded
expect(fooParsed.children[PRIMARY_OUTLET].segments.length).toBe(1);
expect(fooParsed.children[PRIMARY_OUTLET].segments[0].path).toBe('abc');
expect(fooParsed.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({
foo: '(other:val)'
});
});
it('should serialize encoded parens in matrix params', () => {
const testUrl = '/abc;foo=%28one%29';
const parsed = url.parse(testUrl);
expect(url.serialize(parsed)).toBe('/abc;foo=%28one%29');
});
it('should not serialize encoded parens in query params', () => {
const testUrl = '/abc?foo=%28one%29';
const parsed = url.parse(testUrl);
expect(parsed.queryParams).toEqual({foo: '(one)'});
expect(url.serialize(parsed)).toBe('/abc?foo=(one)');
});
// Test special characters in general
// From http://www.ietf.org/rfc/rfc3986.txt
const unreserved = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~`;
it('should encode a minimal set of special characters in queryParams and fragment', () => {
const notEncoded = unreserved + `:@!$'*,();`;
const encode = ` +%&=#[]/?`;
const encoded = `%20%2B%25%26%3D%23%5B%5D%2F%3F`;
const parsed = url.parse('/foo');
parsed.queryParams = {notEncoded, encode};
expect(url.serialize(parsed)).toBe(`/foo?notEncoded=${notEncoded}&encode=${encoded}`);
});
it('should encode a minimal set of special characters in fragment', () => {
const notEncoded = unreserved + `:@!$'*,();`;
const encode = ` +%&=#[]/?`;
const encoded = `%20%2B%25%26%3D%23%5B%5D%2F%3F`;
const parsed = url.parse('/foo');
parsed.fragment = notEncoded + encode;
expect(url.serialize(parsed)).toBe(`/foo#${notEncoded}${encoded}`);
});
it('should encode minimal special characters plus parens and semi-colon in matrix params',
() => {
const notEncoded = unreserved + `:@!$'*,&`;
const encode = ` /%=#()[];?+`;
const encoded = `%20%2F%25%3D%23%28%29%5B%5D%3B%3F%2B`;
const parsed = url.parse('/foo');
parsed.root.children[PRIMARY_OUTLET].segments[0].parameters = {notEncoded, encode};
expect(url.serialize(parsed)).toBe(`/foo;notEncoded=${notEncoded};encode=${encoded}`);
});
it('should encode special characters in the path the same as matrix params', () => {
const notEncoded = unreserved + `:@!$'*,&`;
const encode = ` /%=#()[];?+`;
const encoded = `%20%2F%25%3D%23%28%29%5B%5D%3B%3F%2B`;
const parsed = url.parse('/foo');
parsed.root.children[PRIMARY_OUTLET].segments[0].path = notEncoded + encode;
expect(url.serialize(parsed)).toBe(`/${notEncoded}${encoded}`);
}); });
}); });

View File

@ -243,7 +243,7 @@ export class Driver implements Debuggable, UpdateSource {
} }
private async handlePush(data: any): Promise<void> { private async handlePush(data: any): Promise<void> {
await this.broadcast({ this.broadcast({
type: 'PUSH', type: 'PUSH',
data, data,
}); });
@ -254,7 +254,7 @@ export class Driver implements Debuggable, UpdateSource {
let options: {[key: string]: string | undefined} = {}; let options: {[key: string]: string | undefined} = {};
NOTIFICATION_OPTION_NAMES.filter(name => desc.hasOwnProperty(name)) NOTIFICATION_OPTION_NAMES.filter(name => desc.hasOwnProperty(name))
.forEach(name => options[name] = desc[name]); .forEach(name => options[name] = desc[name]);
await this.scope.registration.showNotification(desc['title'] !, options); this.scope.registration.showNotification(desc['title'] !, options);
} }
private async reportStatus(client: Client, promise: Promise<void>, nonce: number): Promise<void> { private async reportStatus(client: Client, promise: Promise<void>, nonce: number): Promise<void> {
@ -614,7 +614,7 @@ export class Driver implements Debuggable, UpdateSource {
if (!res.ok) { if (!res.ok) {
if (res.status === 404) { if (res.status === 404) {
await this.deleteAllCaches(); await this.deleteAllCaches();
await this.scope.registration.unregister(); this.scope.registration.unregister();
} }
throw new Error('Manifest fetch failed!'); throw new Error('Manifest fetch failed!');
} }
@ -707,7 +707,7 @@ export class Driver implements Debuggable, UpdateSource {
// Firstly, check if the manifest version is correct. // Firstly, check if the manifest version is correct.
if (manifest.configVersion !== SUPPORTED_CONFIG_VERSION) { if (manifest.configVersion !== SUPPORTED_CONFIG_VERSION) {
await this.deleteAllCaches(); await this.deleteAllCaches();
await this.scope.registration.unregister(); this.scope.registration.unregister();
throw new Error( throw new Error(
`Invalid config version: expected ${SUPPORTED_CONFIG_VERSION}, got ${manifest.configVersion}.`); `Invalid config version: expected ${SUPPORTED_CONFIG_VERSION}, got ${manifest.configVersion}.`);
} }

View File

@ -527,7 +527,7 @@ const manifestUpdateHash = sha1(JSON.stringify(manifestUpdate));
expect(await driver.checkForUpdate()).toEqual(true); expect(await driver.checkForUpdate()).toEqual(true);
serverUpdate.assertSawRequestFor('/quux.txt'); serverUpdate.assertSawRequestFor('/quux.txt');
serverUpdate.clearRequests(); serverUpdate.clearRequests();
await driver.updateClient(await scope.clients.get('default')); driver.updateClient(await scope.clients.get('default'));
expect(await makeRequest(scope, '/quux.txt')).toEqual('this is quux v2'); expect(await makeRequest(scope, '/quux.txt')).toEqual('this is quux v2');
serverUpdate.assertNoOtherRequests(); serverUpdate.assertNoOtherRequests();
}); });

View File

@ -60,7 +60,7 @@ export declare class HammerGestureConfig {
} }
/** @experimental */ /** @experimental */
export declare function makeStateKey<T = void>(key: string): StateKey<T>; export declare function makeStateKey<T =
/** @experimental */ /** @experimental */
export declare class Meta { export declare class Meta {

View File

@ -265,12 +265,6 @@ ansi-styles@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
ansi-styles@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
dependencies:
color-convert "^1.9.0"
any-promise@^1.0.0, any-promise@^1.1.0, any-promise@~1.3.0: any-promise@^1.0.0, any-promise@^1.1.0, any-promise@~1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@ -984,14 +978,6 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0" strip-ansi "^3.0.0"
supports-color "^2.0.0" supports-color "^2.0.0"
chalk@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
dependencies:
ansi-styles "^3.2.0"
escape-string-regexp "^1.0.5"
supports-color "^5.2.0"
char-spinner@^1.0.1: char-spinner@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/char-spinner/-/char-spinner-1.0.1.tgz#e6ea67bd247e107112983b7ab0479ed362800081" resolved "https://registry.yarnpkg.com/char-spinner/-/char-spinner-1.0.1.tgz#e6ea67bd247e107112983b7ab0479ed362800081"
@ -1152,16 +1138,6 @@ coffee-script@1.3.3:
version "1.3.3" version "1.3.3"
resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4" resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4"
color-convert@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
dependencies:
color-name "^1.1.1"
color-name@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
colors@0.6.0-1: colors@0.6.0-1:
version "0.6.0-1" version "0.6.0-1"
resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.0-1.tgz#6dbb68ceb8bc60f2b313dcc5ce1599f06d19e67a" resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.0-1.tgz#6dbb68ceb8bc60f2b313dcc5ce1599f06d19e67a"
@ -1944,7 +1920,7 @@ didyoumean@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.1.tgz#e92edfdada6537d484d73c0172fd1eba0c4976ff" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.1.tgz#e92edfdada6537d484d73c0172fd1eba0c4976ff"
diff@^2.0.2: diff@^2.0.2, diff@^2.2.3:
version "2.2.3" version "2.2.3"
resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99" resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99"
@ -1952,10 +1928,6 @@ diff@^3.2.0:
version "3.3.1" version "3.3.1"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
diff@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c"
doctrine@^0.7.2: doctrine@^0.7.2:
version "0.7.2" version "0.7.2"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523"
@ -3369,10 +3341,6 @@ has-flag@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
has-gulplog@^0.1.0: has-gulplog@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce"
@ -6848,12 +6816,6 @@ supports-color@^3.1.0:
dependencies: dependencies:
has-flag "^1.0.0" has-flag "^1.0.0"
supports-color@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a"
dependencies:
has-flag "^3.0.0"
symbol-observable@1.0.1: symbol-observable@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
@ -7116,13 +7078,14 @@ try-require@^1.0.0:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/try-require/-/try-require-1.2.1.tgz#34489a2cac0c09c1cc10ed91ba011594d4333be2" resolved "https://registry.yarnpkg.com/try-require/-/try-require-1.2.1.tgz#34489a2cac0c09c1cc10ed91ba011594d4333be2"
ts-api-guardian@^0.3.0: ts-api-guardian@0.2.2:
version "0.3.0" version "0.2.2"
resolved "https://registry.yarnpkg.com/ts-api-guardian/-/ts-api-guardian-0.3.0.tgz#c5fbba9991840328f5ed0c89765a23e707645aa3" resolved "https://registry.yarnpkg.com/ts-api-guardian/-/ts-api-guardian-0.2.2.tgz#b23bbb2865d0c4aee161730a74f59a00c4f06c8b"
dependencies: dependencies:
chalk "^2.3.1" chalk "^1.1.3"
diff "^3.4.0" diff "^2.2.3"
minimist "^1.2.0" minimist "^1.2.0"
typescript "2.0.10"
tsickle@0.26.0: tsickle@0.26.0:
version "0.26.0" version "0.26.0"
@ -7227,6 +7190,10 @@ typedarray@^0.0.6:
version "0.0.6" version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@2.0.10:
version "2.0.10"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.0.10.tgz#ccdd4ed86fd5550a407101a0814012e1b3fac3dd"
typescript@2.6.x: typescript@2.6.x:
version "2.6.2" version "2.6.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4"