Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
a10bf34471 | |||
38146a2cd1 |
@ -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:
|
||||||
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -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)
|
||||||
|
|
||||||
|
18
WORKSPACE
18
WORKSPACE
@ -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")
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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!!');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
@ -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>
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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`.
|
||||||
|
@ -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",
|
||||||
|
@ -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'];
|
||||||
});
|
});
|
||||||
|
@ -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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -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
|
||||||
|
@ -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>' };
|
||||||
|
@ -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
|
||||||
|
@ -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'),
|
||||||
|
@ -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);
|
||||||
];
|
|
||||||
});
|
});
|
||||||
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = function disambiguateByDeprecated() {
|
|
||||||
return (alias, originatingDoc, docs) => docs.filter(doc => doc.deprecated === undefined);
|
|
||||||
};
|
|
@ -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' },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
@ -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 },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -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]);
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
@ -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"
|
||||||
|
@ -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.0‑beta.4 |
|
2018-02-14 | 5.2.5 | 6.0.0‑beta.4 |
|
||||||
2018-02-21 | 5.2.6 | 6.0.0‑beta.5 |
|
2018-02-21 | 5.2.6 | 6.0.0‑beta.5 |
|
||||||
2018-02-28 | 5.2.7 | 6.0.0‑beta.6 |
|
2018-02-28 | 5.2.7 | 6.0.0‑beta.6 |
|
||||||
2018-03-07 | 5.2.8 | 6.0.0‑beta.7 |
|
2018-03-07 | 5.2.8 | 6.0.0‑rc.0 |
|
||||||
2018-03-14 | 5.2.9 | 6.0.0‑rc.0 |
|
2018-03-14 | 5.2.9 | 6.0.0‑rc.1 |
|
||||||
2018-03-21 | 5.2.10 | 6.0.0‑rc.1 |
|
2018-03-21 | 5.2.10 | 6.0.0‑rc.2 |
|
||||||
2018-03-28 | 5.2.11 | 6.0.0‑rc.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
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
),
|
),
|
||||||
|
@ -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",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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}`);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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}.`);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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 {
|
||||||
|
55
yarn.lock
55
yarn.lock
@ -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"
|
||||||
|
Reference in New Issue
Block a user