mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f37ed1060 | |||
| 5c85b4f1e9 | |||
| 22bc6ef22a | |||
| bf928d1c9e | |||
| d11c2f915b | |||
| 98c99e5073 | |||
| 2c63108faa | |||
| 0ff48a1266 | |||
| ea2a3f8335 | |||
| cbed4851a3 | |||
| 7c157780a9 | |||
| cc1b2a5373 | |||
| 5076185fc8 | |||
| 65375f4c21 | |||
| 068a6070dc | |||
| 47e9761a01 | |||
| bef52d20b5 | |||
| fe50710021 | |||
| 71b66fb862 | |||
| 8db05b408e | |||
| 351610ca8d | |||
| ef78e33560 | |||
| 12b8a6e351 | |||
| 260ac20e92 | |||
| aed48e00d2 | |||
| a9d46e4952 | |||
| 2f19ad9b46 | |||
| 81678e62db | |||
| cf82fbceba | |||
| 1d67cb0ce1 | |||
| 318bd83a6e | |||
| f767c22b31 | |||
| 8346a6dca2 | |||
| 6397885e74 | |||
| 8cee56e8c5 | |||
| a1b9995731 | |||
| 35f7ff047a | |||
| 4ad691a33d | |||
| c5af3f8617 | |||
| bc1032866c | |||
| 63e6d1a896 | |||
| cb9fd9b4d7 | |||
| d5dca0764c | |||
| bcd1a09dec | |||
| 898c0134e7 | |||
| 763d2150cc | |||
| beacbfcb8e | |||
| f72319cf6e | |||
| 5877b3f702 | |||
| cf310ba1fa | |||
| c2d2953ee4 |
@@ -42,6 +42,16 @@ build --watchfs
|
||||
run --nolegacy_external_runfiles
|
||||
test --nolegacy_external_runfiles
|
||||
|
||||
# Turn on --incompatible_strict_action_env which was on by default
|
||||
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
|
||||
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
|
||||
# This flag is needed to so that the bazel cache is not invalidated
|
||||
# when running bazel via `yarn bazel`.
|
||||
# See https://github.com/angular/angular/issues/27514.
|
||||
build --incompatible_strict_action_env
|
||||
run --incompatible_strict_action_env
|
||||
test --incompatible_strict_action_env
|
||||
|
||||
###############################
|
||||
# Release support #
|
||||
# Turn on these settings with #
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
<a name="7.2.3"></a>
|
||||
## [7.2.3](https://github.com/angular/angular/compare/7.2.2...7.2.3) (2019-01-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bazel:** add [@npm](https://github.com/npm)//tslib dep to e2e ts_library target in bazel-workspace schematic ([#28358](https://github.com/angular/angular/issues/28358)) ([8cee56e](https://github.com/angular/angular/commit/8cee56e))
|
||||
* **bazel:** Bazel-workspace schematics should run in ScopedTree ([#28349](https://github.com/angular/angular/issues/28349)) ([260ac20](https://github.com/angular/angular/commit/260ac20))
|
||||
* **bazel:** Builder should invoke local bazel/iblaze ([#28303](https://github.com/angular/angular/issues/28303)) ([12b8a6e](https://github.com/angular/angular/commit/12b8a6e))
|
||||
* **bazel:** ng-new should run yarn install ([#28381](https://github.com/angular/angular/issues/28381)) ([a9d46e4](https://github.com/angular/angular/commit/a9d46e4))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* yarn version upgrade ([#28360](https://github.com/angular/angular/issues/28360)) ([cc1b2a5](https://github.com/angular/angular/commit/cc1b2a5))
|
||||
|
||||
|
||||
|
||||
<a name="7.2.2"></a>
|
||||
## [7.2.2](https://github.com/angular/angular/compare/7.2.1...7.2.2) (2019-01-22)
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ local_repository(
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
|
||||
# Bazel version must be at least v0.21.0 because:
|
||||
# - 0.21.0 --experimental_strict_action_env flag turned on by default which fixes cache when
|
||||
# running `yarn bazel` (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
||||
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
|
||||
# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
||||
check_bazel_version("0.21.0", """
|
||||
You no longer need to install Bazel on your machine.
|
||||
Angular has a dependency on the @bazel/bazel package which supplies it.
|
||||
|
||||
@@ -1508,7 +1508,7 @@ done manually.
|
||||
|
||||
When `true`, this option tells the compiler not to check the TypeScript version.
|
||||
The compiler will skip checking and will not error out when an unsupported version of TypeScript is used.
|
||||
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behaviour.
|
||||
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behavior.
|
||||
|
||||
This option is `false` by default.
|
||||
|
||||
|
||||
@@ -273,8 +273,8 @@ The CLI uses [Autoprefixer](https://github.com/postcss/autoprefixer) to ensure c
|
||||
You may find it necessary to target specific browsers or exclude certain browser versions from your build.
|
||||
|
||||
Internally, Autoprefixer relies on a library called [Browserslist](https://github.com/browserslist/browserslist) to figure out which browsers to support with prefixing.
|
||||
Browserlist looks for configuration options in a `browserlist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
|
||||
Autoprefixer looks for the Browserlist configuration when it prefixes your CSS.
|
||||
Browserlist looks for configuration options in a `browserslist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
|
||||
Autoprefixer looks for the `browserslist` configuration when it prefixes your CSS.
|
||||
|
||||
* You can tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
|
||||
```
|
||||
|
||||
@@ -53,7 +53,7 @@ Workspace-wide `node_modules` dependencies are visible to this project.
|
||||
| `app/` | Contains the component files in which your app logic and data are defined. See details in [App source folder](#app-src) below. |
|
||||
| `assets/` | Contains image files and other asset files to be copied as-is when you build your application. |
|
||||
| `environments/` | Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations. |
|
||||
| `browserlist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserlist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||
| `favicon.ico` | An icon to use for this app in the bookmark bar. |
|
||||
| `index.html` | The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files when building your app, so you typically don't need to add any `<script>` or` <link>` tags here manually. |
|
||||
| `main.ts` | The main entry point for your app. Compiles the application with the [JIT compiler](https://angular.io/guide/glossary#jit) and bootstraps the application's root module (AppModule) to run in the browser. You can also use the [AOT compiler](https://angular.io/guide/aot-compiler) without changing any code by appending the `--aot` flag to the CLI `build` and `serve` commands. |
|
||||
|
||||
@@ -124,7 +124,7 @@ calls the lifecycle hook methods in the following sequence at specific moments:
|
||||
|
||||
Respond after Angular checks the component's views and child views / the view that a directive is in.
|
||||
|
||||
Called after the `ngAfterViewInit` and every subsequent `ngAfterContentChecked()`.
|
||||
Called after the `ngAfterViewInit()` and every subsequent `ngAfterContentChecked()`.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 154 KiB |
@@ -698,5 +698,13 @@
|
||||
"website": "https://brianflove.com",
|
||||
"bio": "Brian is a software engineer and GDE in Angular with a passion for learning, writing, speaking, teaching and mentoring. Brian has been building web applications for over 20 years and has long been a fanboy of JavaScript. When not in front of his Macbook Pro Brian is in the Rocky Mountains skiing or hiking.",
|
||||
"group": "GDE"
|
||||
},
|
||||
"jeffbcross": {
|
||||
"name": "Jeff Cross",
|
||||
"picture": "jeff-cross.jpg",
|
||||
"twitter": "jeffbcross",
|
||||
"website": "https://nrwl.io/",
|
||||
"bio": "Jeff is an Angular Consultant at nrwl.io where he helps enterprise teams succeed with Angular. Prior to founding Nrwl, Jeff was one of the earliest members of the Angular Core Team at Google, and contributed to many of the early state management and performance efforts of AngularJS and Angular.",
|
||||
"group": "GDE"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
<td>Atlanta, Georgia</td>
|
||||
<td>January 9 - 12, 2019</td>
|
||||
</tr>
|
||||
<!-- ng-India 2019-->
|
||||
<tr>
|
||||
<th><a href="https://www.ng-ind.com/" title="ng-India">ng-India</a></th>
|
||||
<td>Gurgaon, India</td>
|
||||
<td>February 23, 2019</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -753,6 +753,10 @@
|
||||
{
|
||||
"title": "日本語版",
|
||||
"url": "https://angular.jp/"
|
||||
},
|
||||
{
|
||||
"title": "한국어",
|
||||
"url": "https://angular.kr/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ Inject `HttpClient` into the constructor in a private property called `http`.
|
||||
</code-example>
|
||||
|
||||
Keep injecting the `MessageService`. You'll call it so frequently that
|
||||
you'll wrap it in private `log` method.
|
||||
you'll wrap it in a private `log()` method.
|
||||
|
||||
<code-example
|
||||
path="toh-pt6/src/app/hero.service.ts"
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@
|
||||
"build": "yarn ~~build",
|
||||
"prebuild-local": "yarn setup-local",
|
||||
"build-local": "yarn ~~build",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 02d2ec250",
|
||||
"extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 699743282",
|
||||
"lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint",
|
||||
"test": "yarn check-env && ng test",
|
||||
"pree2e": "yarn check-env && yarn update-webdriver",
|
||||
@@ -71,7 +71,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.9.0 <11.0.0",
|
||||
"yarn": ">=1.10.1 <1.13.0"
|
||||
"yarn": ">=1.10.1 <1.14.0"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@@ -107,7 +107,7 @@
|
||||
"canonical-path": "1.0.0",
|
||||
"chalk": "^2.1.0",
|
||||
"cjson": "^0.5.0",
|
||||
"codelyzer": "~4.2.1",
|
||||
"codelyzer": "~4.5.0",
|
||||
"cross-spawn": "^5.1.0",
|
||||
"css-selector-parser": "^1.3.0",
|
||||
"dgeni": "^0.4.11",
|
||||
|
||||
@@ -9,7 +9,7 @@ const SRC_DIR = resolve(__dirname, '../src');
|
||||
const DIST_DIR = resolve(__dirname, '../dist');
|
||||
|
||||
// Run
|
||||
_main(process.argv.slice(2));
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
|
||||
@@ -169,6 +169,13 @@ describe('AppComponent', () => {
|
||||
|
||||
expect(component.tocMaxHeight).toMatch(/^\d+\.\d{2}$/);
|
||||
});
|
||||
|
||||
it('should update `scrollService.updateScrollPositonInHistory()`', () => {
|
||||
const scrollService = fixture.debugElement.injector.get<ScrollService>(ScrollService);
|
||||
spyOn(scrollService, 'updateScrollPositionInHistory');
|
||||
component.onScroll();
|
||||
expect(scrollService.updateScrollPositionInHistory).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('SideNav', () => {
|
||||
@@ -461,11 +468,15 @@ describe('AppComponent', () => {
|
||||
let scrollService: ScrollService;
|
||||
let scrollSpy: jasmine.Spy;
|
||||
let scrollToTopSpy: jasmine.Spy;
|
||||
let scrollAfterRenderSpy: jasmine.Spy;
|
||||
let removeStoredScrollPositionSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
scrollService = fixture.debugElement.injector.get<ScrollService>(ScrollService);
|
||||
scrollSpy = spyOn(scrollService, 'scroll');
|
||||
scrollToTopSpy = spyOn(scrollService, 'scrollToTop');
|
||||
scrollAfterRenderSpy = spyOn(scrollService, 'scrollAfterRender');
|
||||
removeStoredScrollPositionSpy = spyOn(scrollService, 'removeStoredScrollPosition');
|
||||
});
|
||||
|
||||
it('should not scroll immediately when the docId (path) changes', () => {
|
||||
@@ -510,33 +521,24 @@ describe('AppComponent', () => {
|
||||
expect(scrollSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should scroll to top when call `onDocRemoved` directly', () => {
|
||||
scrollToTopSpy.calls.reset();
|
||||
|
||||
it('should call `removeStoredScrollPosition` when call `onDocRemoved` directly', () => {
|
||||
component.onDocRemoved();
|
||||
expect(scrollToTopSpy).toHaveBeenCalled();
|
||||
expect(removeStoredScrollPositionSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should scroll after a delay when call `onDocInserted` directly', fakeAsync(() => {
|
||||
it('should call `scrollAfterRender` when call `onDocInserted` directly', (() => {
|
||||
component.onDocInserted();
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).toHaveBeenCalled();
|
||||
expect(scrollAfterRenderSpy).toHaveBeenCalledWith(scrollDelay);
|
||||
}));
|
||||
|
||||
it('should scroll (via `onDocInserted`) when finish navigating to a new doc', fakeAsync(() => {
|
||||
expect(scrollToTopSpy).not.toHaveBeenCalled();
|
||||
|
||||
it('should call `scrollAfterRender` (via `onDocInserted`) when navigate to a new Doc', fakeAsync(() => {
|
||||
locationService.go('guide/pipes');
|
||||
tick(1); // triggers the HTTP response for the document
|
||||
tick(1); // triggers the HTTP response for the document
|
||||
fixture.detectChanges(); // triggers the event that calls `onDocInserted`
|
||||
|
||||
expect(scrollToTopSpy).toHaveBeenCalled();
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
expect(scrollAfterRenderSpy).toHaveBeenCalledWith(scrollDelay);
|
||||
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).toHaveBeenCalled();
|
||||
tick(500); // there are other outstanding timers in the AppComponent that are not relevant
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
if (path === this.currentPath) {
|
||||
// scroll only if on same page (most likely a change to the hash)
|
||||
this.autoScroll();
|
||||
this.scrollService.scroll();
|
||||
} else {
|
||||
// don't scroll; leave that to `onDocRendered`
|
||||
this.currentPath = path;
|
||||
@@ -187,11 +187,6 @@ export class AppComponent implements OnInit {
|
||||
.subscribe(() => this.updateShell());
|
||||
}
|
||||
|
||||
// Scroll to the anchor in the hash fragment or top of doc.
|
||||
autoScroll() {
|
||||
this.scrollService.scroll();
|
||||
}
|
||||
|
||||
onDocReady() {
|
||||
// About to transition to new view.
|
||||
this.isTransitioning = true;
|
||||
@@ -204,9 +199,7 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
|
||||
onDocRemoved() {
|
||||
// The previous document has been removed.
|
||||
// Scroll to top to restore a clean visual state for the new document.
|
||||
this.scrollService.scrollToTop();
|
||||
this.scrollService.removeStoredScrollPosition();
|
||||
}
|
||||
|
||||
onDocInserted() {
|
||||
@@ -216,9 +209,8 @@ export class AppComponent implements OnInit {
|
||||
// (e.g. sidenav, host classes) needs to happen asynchronously.
|
||||
setTimeout(() => this.updateShell());
|
||||
|
||||
// Scroll 500ms after the new document has been inserted into the doc-viewer.
|
||||
// The delay is to allow time for async layout to complete.
|
||||
setTimeout(() => this.autoScroll(), 500);
|
||||
// Scroll the good position depending on the context
|
||||
this.scrollService.scrollAfterRender(500);
|
||||
}
|
||||
|
||||
onDocRendered() {
|
||||
@@ -242,7 +234,7 @@ export class AppComponent implements OnInit {
|
||||
|
||||
@HostListener('window:resize', ['$event.target.innerWidth'])
|
||||
onResize(width: number) {
|
||||
this.isSideBySide = width > this.sideBySideWidth;
|
||||
this.isSideBySide = width >= this.sideBySideWidth;
|
||||
this.showFloatingToc.next(width > this.showFloatingTocWidth);
|
||||
|
||||
if (this.isSideBySide && !this.isSideNavDoc) {
|
||||
@@ -256,7 +248,6 @@ export class AppComponent implements OnInit {
|
||||
|
||||
@HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey'])
|
||||
onClick(eventTarget: HTMLElement, button: number, ctrlKey: boolean, metaKey: boolean, altKey: boolean): boolean {
|
||||
|
||||
// Hide the search results if we clicked outside both the "search box" and the "search results"
|
||||
if (!this.searchElements.some(element => element.nativeElement.contains(eventTarget))) {
|
||||
this.hideSearchResults();
|
||||
@@ -348,6 +339,9 @@ export class AppComponent implements OnInit {
|
||||
// Dynamically change height of table of contents container
|
||||
@HostListener('window:scroll')
|
||||
onScroll() {
|
||||
|
||||
this.scrollService.updateScrollPositionInHistory();
|
||||
|
||||
if (!this.tocMaxHeightOffset) {
|
||||
// Must wait until `mat-toolbar` is measurable.
|
||||
const el = this.hostElement.nativeElement as Element;
|
||||
|
||||
@@ -46,7 +46,7 @@ export interface TabInfo {
|
||||
export class CodeTabsComponent implements OnInit, AfterViewInit {
|
||||
tabs: TabInfo[];
|
||||
|
||||
@Input('linenums') linenums: string;
|
||||
@Input() linenums: string;
|
||||
|
||||
@ViewChild('content') content;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { DocumentContents } from 'app/documents/document.service';
|
||||
export class DtComponent {
|
||||
|
||||
@Input() on = false;
|
||||
@Input('doc') doc: DocumentContents;
|
||||
@Input() doc: DocumentContents;
|
||||
@Output() docChange = new EventEmitter<DocumentContents>();
|
||||
|
||||
@ViewChild('dt', { read: ElementRef })
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ReflectiveInjector } from '@angular/core';
|
||||
import { PlatformLocation } from '@angular/common';
|
||||
import { Location, LocationStrategy, PlatformLocation, ViewportScroller } from '@angular/common';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { MockLocationStrategy, SpyLocation } from '@angular/common/testing';
|
||||
import { fakeAsync, tick } from '@angular/core/testing';
|
||||
|
||||
import { ScrollService, topMargin } from './scroll.service';
|
||||
|
||||
@@ -8,8 +10,9 @@ describe('ScrollService', () => {
|
||||
const topOfPageElem = {} as Element;
|
||||
let injector: ReflectiveInjector;
|
||||
let document: MockDocument;
|
||||
let location: MockPlatformLocation;
|
||||
let platformLocation: MockPlatformLocation;
|
||||
let scrollService: ScrollService;
|
||||
let location: SpyLocation;
|
||||
|
||||
class MockPlatformLocation {
|
||||
hash: string;
|
||||
@@ -27,6 +30,11 @@ describe('ScrollService', () => {
|
||||
scrollIntoView = jasmine.createSpy('Element scrollIntoView');
|
||||
}
|
||||
|
||||
const viewportScrollerStub = jasmine.createSpyObj(
|
||||
'viewportScroller',
|
||||
['getScrollPosition', 'scrollToPosition']);
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(window, 'scrollBy');
|
||||
});
|
||||
@@ -34,12 +42,24 @@ describe('ScrollService', () => {
|
||||
beforeEach(() => {
|
||||
injector = ReflectiveInjector.resolveAndCreate([
|
||||
ScrollService,
|
||||
{ provide: Location, useClass: SpyLocation },
|
||||
{ provide: DOCUMENT, useClass: MockDocument },
|
||||
{ provide: PlatformLocation, useClass: MockPlatformLocation }
|
||||
{ provide: PlatformLocation, useClass: MockPlatformLocation },
|
||||
{ provide: ViewportScroller, useValue: viewportScrollerStub },
|
||||
{ provide: LocationStrategy, useClass: MockLocationStrategy }
|
||||
]);
|
||||
location = injector.get(PlatformLocation);
|
||||
platformLocation = injector.get(PlatformLocation);
|
||||
document = injector.get(DOCUMENT);
|
||||
scrollService = injector.get(ScrollService);
|
||||
location = injector.get(Location);
|
||||
});
|
||||
|
||||
it('should set `scrollRestoration` to `manual` if supported', () => {
|
||||
if (scrollService.supportManualScrollRestoration) {
|
||||
expect(window.history.scrollRestoration).toBe('manual');
|
||||
} else {
|
||||
expect(window.history.scrollRestoration).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
describe('#topOffset', () => {
|
||||
@@ -107,7 +127,7 @@ describe('ScrollService', () => {
|
||||
|
||||
describe('#scroll', () => {
|
||||
it('should scroll to the top if there is no hash', () => {
|
||||
location.hash = '';
|
||||
platformLocation.hash = '';
|
||||
|
||||
const topOfPage = new MockElement();
|
||||
document.getElementById.and
|
||||
@@ -118,7 +138,7 @@ describe('ScrollService', () => {
|
||||
});
|
||||
|
||||
it('should not scroll if the hash does not match an element id', () => {
|
||||
location.hash = 'not-found';
|
||||
platformLocation.hash = 'not-found';
|
||||
document.getElementById.and.returnValue(null);
|
||||
|
||||
scrollService.scroll();
|
||||
@@ -128,7 +148,7 @@ describe('ScrollService', () => {
|
||||
|
||||
it('should scroll to the element whose id matches the hash', () => {
|
||||
const element = new MockElement();
|
||||
location.hash = 'some-id';
|
||||
platformLocation.hash = 'some-id';
|
||||
document.getElementById.and.returnValue(element);
|
||||
|
||||
scrollService.scroll();
|
||||
@@ -139,7 +159,7 @@ describe('ScrollService', () => {
|
||||
|
||||
it('should scroll to the element whose id matches the hash with encoded characters', () => {
|
||||
const element = new MockElement();
|
||||
location.hash = '%F0%9F%91%8D'; // 👍
|
||||
platformLocation.hash = '%F0%9F%91%8D'; // 👍
|
||||
document.getElementById.and.returnValue(element);
|
||||
|
||||
scrollService.scroll();
|
||||
@@ -210,4 +230,136 @@ describe('ScrollService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isLocationWithHash', () => {
|
||||
it('should return true when the location has a hash', () => {
|
||||
platformLocation.hash = 'anchor';
|
||||
expect(scrollService.isLocationWithHash()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when the location has no hash', () => {
|
||||
platformLocation.hash = '';
|
||||
expect(scrollService.isLocationWithHash()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#needToFixScrollPosition', async() => {
|
||||
it('should return true when popState event was fired after a back navigation if the browser supports ' +
|
||||
'scrollRestoration`. Otherwise, needToFixScrollPosition() returns false', () => {
|
||||
|
||||
if (scrollService.supportManualScrollRestoration) {
|
||||
location.go('/initial-url1');
|
||||
// We simulate a scroll down
|
||||
location.replaceState('/initial-url1', 'hack', {scrollPosition: [2000, 0]});
|
||||
location.go('/initial-url2');
|
||||
location.back();
|
||||
|
||||
expect(scrollService.popStateFired).toBe(true);
|
||||
expect(scrollService.scrollPosition).toEqual([2000, 0]);
|
||||
expect(scrollService.needToFixScrollPosition()).toBe(true);
|
||||
} else {
|
||||
location.go('/initial-url1');
|
||||
location.go('/initial-url2');
|
||||
location.back();
|
||||
|
||||
expect(scrollService.popStateFired).toBe(false); // popStateFired is always false
|
||||
expect(scrollService.scrollPosition).toEqual([0, 0]); // scrollPosition always equals [0, 0]
|
||||
expect(scrollService.needToFixScrollPosition()).toBe(false);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
it('should return true when popState event was fired after a forward navigation if the browser supports ' +
|
||||
'scrollRestoration`. Otherwise, needToFixScrollPosition() returns false', () => {
|
||||
|
||||
if (scrollService.supportManualScrollRestoration) {
|
||||
location.go('/initial-url1');
|
||||
location.go('/initial-url2');
|
||||
// We simulate a scroll down
|
||||
location.replaceState('/initial-url1', 'hack', {scrollPosition: [2000, 0]});
|
||||
|
||||
location.back();
|
||||
scrollService.popStateFired = false;
|
||||
scrollService.scrollPosition = [0, 0];
|
||||
location.forward();
|
||||
|
||||
expect(scrollService.popStateFired).toBe(true);
|
||||
expect(scrollService.scrollPosition).toEqual([2000, 0]);
|
||||
expect(scrollService.needToFixScrollPosition()).toBe(true);
|
||||
} else {
|
||||
location.go('/initial-url1');
|
||||
location.go('/initial-url2');
|
||||
location.back();
|
||||
location.forward();
|
||||
|
||||
expect(scrollService.popStateFired).toBe(false); // popStateFired is always false
|
||||
expect(scrollService.scrollPosition).toEqual([0, 0]); // scrollPosition always equals [0, 0]
|
||||
expect(scrollService.needToFixScrollPosition()).toBe(false);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('#scrollAfterRender', async() => {
|
||||
|
||||
let scrollSpy: jasmine.Spy;
|
||||
let scrollToTopSpy: jasmine.Spy;
|
||||
let needToFixScrollPositionSpy: jasmine.Spy;
|
||||
let scrollToPosition: jasmine.Spy;
|
||||
let isLocationWithHashSpy: jasmine.Spy;
|
||||
let getStoredScrollPositionSpy: jasmine.Spy;
|
||||
const scrollDelay = 500;
|
||||
|
||||
beforeEach(() => {
|
||||
scrollSpy = spyOn(scrollService, 'scroll');
|
||||
scrollToTopSpy = spyOn(scrollService, 'scrollToTop');
|
||||
scrollToPosition = spyOn(scrollService, 'scrollToPosition');
|
||||
needToFixScrollPositionSpy = spyOn(scrollService, 'needToFixScrollPosition');
|
||||
getStoredScrollPositionSpy = spyOn(scrollService, 'getStoredScrollPosition');
|
||||
isLocationWithHashSpy = spyOn(scrollService, 'isLocationWithHash');
|
||||
});
|
||||
|
||||
|
||||
it('should call `scroll` when we navigate to a location with anchor', fakeAsync(() => {
|
||||
needToFixScrollPositionSpy.and.returnValue(false);
|
||||
getStoredScrollPositionSpy.and.returnValue(null);
|
||||
isLocationWithHashSpy.and.returnValue(true);
|
||||
|
||||
scrollService.scrollAfterRender(scrollDelay);
|
||||
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should call `scrollToTop` when we navigate to a location without anchor', fakeAsync(() => {
|
||||
needToFixScrollPositionSpy.and.returnValue(false);
|
||||
getStoredScrollPositionSpy.and.returnValue(null);
|
||||
isLocationWithHashSpy.and.returnValue(false);
|
||||
|
||||
scrollService.scrollAfterRender(scrollDelay);
|
||||
|
||||
expect(scrollToTopSpy).toHaveBeenCalled();
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should call `viewportScroller.scrollToPosition` when we reload a page', fakeAsync(() => {
|
||||
getStoredScrollPositionSpy.and.returnValue([0, 1000]);
|
||||
|
||||
scrollService.scrollAfterRender(scrollDelay);
|
||||
|
||||
expect(viewportScrollerStub.scrollToPosition).toHaveBeenCalled();
|
||||
expect(getStoredScrollPositionSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should call `scrollToPosition` after a popState', fakeAsync(() => {
|
||||
needToFixScrollPositionSpy.and.returnValue(true);
|
||||
getStoredScrollPositionSpy.and.returnValue(null);
|
||||
scrollService.scrollAfterRender(scrollDelay);
|
||||
expect(scrollToPosition).toHaveBeenCalled();
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
expect(scrollToTopSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Injectable, Inject } from '@angular/core';
|
||||
import { PlatformLocation } from '@angular/common';
|
||||
import { Location, PlatformLocation, ViewportScroller } from '@angular/common';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { fromEvent } from 'rxjs';
|
||||
|
||||
@@ -13,6 +13,13 @@ export class ScrollService {
|
||||
private _topOffset: number | null;
|
||||
private _topOfPageElement: Element;
|
||||
|
||||
// true when popState event has been fired.
|
||||
popStateFired = false;
|
||||
// scroll position which has to be restored after the popState event
|
||||
scrollPosition: [number, number] = [0, 0];
|
||||
// true when the browser supports `scrollTo`, `scrollX`, `scrollY` and `scrollRestoration`
|
||||
supportManualScrollRestoration: boolean;
|
||||
|
||||
// Offset from the top of the document to bottom of any static elements
|
||||
// at the top (e.g. toolbar) + some margin
|
||||
get topOffset() {
|
||||
@@ -32,9 +39,37 @@ export class ScrollService {
|
||||
|
||||
constructor(
|
||||
@Inject(DOCUMENT) private document: any,
|
||||
private location: PlatformLocation) {
|
||||
private platformLocation: PlatformLocation,
|
||||
private viewportScroller: ViewportScroller,
|
||||
private location: Location) {
|
||||
// On resize, the toolbar might change height, so "invalidate" the top offset.
|
||||
fromEvent(window, 'resize').subscribe(() => this._topOffset = null);
|
||||
|
||||
try {
|
||||
this.supportManualScrollRestoration = !!window && !!window.scrollTo && 'scrollX' in window
|
||||
&& 'scrollY' in window && !!history && !!history.scrollRestoration;
|
||||
} catch {
|
||||
this.supportManualScrollRestoration = false;
|
||||
}
|
||||
|
||||
// Change scroll restoration strategy to `manual` if it's supported
|
||||
if (this.supportManualScrollRestoration) {
|
||||
history.scrollRestoration = 'manual';
|
||||
// we have to detect forward and back navigation thanks to popState event
|
||||
this.location.subscribe(event => {
|
||||
// the type is `hashchange` when the fragment identifier of the URL has changed. It allows us to go to position
|
||||
// just before a click on an anchor
|
||||
if (event.type === 'hashchange') {
|
||||
this.scrollToPosition();
|
||||
} else {
|
||||
// The popstate event is always triggered by doing a browser action such as a click on the back or forward button.
|
||||
// It can be follow by a event of type `hashchange`.
|
||||
this.popStateFired = true;
|
||||
// we always should have a scrollPosition in our state history
|
||||
this.scrollPosition = event.state ? event.state['scrollPosition'] : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,6 +85,44 @@ export class ScrollService {
|
||||
this.scrollToElement(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if the current location has a hash
|
||||
*/
|
||||
isLocationWithHash(): boolean {
|
||||
return !!this.getCurrentHash();
|
||||
}
|
||||
|
||||
/**
|
||||
* When we load a document, we have to scroll to the correct position depending on whether this is a new location,
|
||||
* a back/forward in the history, or a refresh
|
||||
* @param delay before we scroll to the good position
|
||||
*/
|
||||
scrollAfterRender(delay: number) {
|
||||
// If we do rendering following a refresh, we use the scroll position from the storage.
|
||||
const storedScrollPosition = this.getStoredScrollPosition();
|
||||
if (storedScrollPosition) {
|
||||
this.viewportScroller.scrollToPosition(storedScrollPosition);
|
||||
} else {
|
||||
if (this.needToFixScrollPosition()) {
|
||||
// The document was reloaded following a popState `event` (called by the forward/back button), so we manage
|
||||
// the scroll position
|
||||
this.scrollToPosition();
|
||||
} else {
|
||||
// The document was loaded either of the following cases: a direct navigation via typing the URL in the
|
||||
// address bar or a click on a link. If the location contains a hash, we have to wait for async
|
||||
// layout.
|
||||
if (this.isLocationWithHash()) {
|
||||
// Scroll 500ms after the new document has been inserted into the doc-viewer.
|
||||
// The delay is to allow time for async layout to complete.
|
||||
setTimeout(() => this.scroll(), delay);
|
||||
} else {
|
||||
// If the location doesn't contain a hash, we scroll to the top of the page.
|
||||
this.scrollToTop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to the element.
|
||||
* Don't scroll if no element.
|
||||
@@ -79,10 +152,42 @@ export class ScrollService {
|
||||
this.scrollToElement(this.topOfPageElement);
|
||||
}
|
||||
|
||||
scrollToPosition() {
|
||||
this.viewportScroller.scrollToPosition(this.scrollPosition);
|
||||
this.popStateFired = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state with scroll position into history.
|
||||
*/
|
||||
updateScrollPositionInHistory() {
|
||||
if (this.supportManualScrollRestoration) {
|
||||
const currentScrollPosition = this.viewportScroller.getScrollPosition();
|
||||
this.location.replaceState(this.location.path(true), undefined, {scrollPosition: currentScrollPosition});
|
||||
window.sessionStorage.setItem('scrollPosition', currentScrollPosition.toString());
|
||||
}
|
||||
}
|
||||
|
||||
getStoredScrollPosition(): [number, number] | null {
|
||||
const position = window.sessionStorage.getItem('scrollPosition');
|
||||
return position ? JSON.parse('[' + position + ']') : null;
|
||||
}
|
||||
|
||||
removeStoredScrollPosition() {
|
||||
window.sessionStorage.removeItem('scrollPosition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the scroll position need to be manually fixed after popState event
|
||||
*/
|
||||
needToFixScrollPosition(): boolean {
|
||||
return this.popStateFired && this.scrollPosition && this.supportManualScrollRestoration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hash fragment from the `PlatformLocation`, minus the leading `#`.
|
||||
*/
|
||||
private getCurrentHash() {
|
||||
return decodeURIComponent(this.location.hash.replace(/^#/, ''));
|
||||
return decodeURIComponent(this.platformLocation.hash.replace(/^#/, ''));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ aio-shell.page-resources mat-toolbar.mat-toolbar {
|
||||
|
||||
// DOCS PAGES OVERRIDE: HAMBURGER
|
||||
aio-shell.folder-api mat-toolbar.mat-toolbar,
|
||||
aio-shell.folder-cli mat-toolbar.mat-toolbar,
|
||||
aio-shell.folder-docs mat-toolbar.mat-toolbar,
|
||||
aio-shell.folder-guide mat-toolbar.mat-toolbar,
|
||||
aio-shell.folder-tutorial mat-toolbar.mat-toolbar {
|
||||
|
||||
@@ -74,6 +74,12 @@
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
&.property-table {
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.class-overview {
|
||||
@@ -87,19 +93,6 @@
|
||||
.short-description {
|
||||
margin: 6px 0 0 10px;
|
||||
}
|
||||
|
||||
.properties-table {
|
||||
font-size: 14px;
|
||||
|
||||
thead th {
|
||||
&:nth-child(1) {
|
||||
width: 20%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
|
||||
@@ -7,10 +7,14 @@ describe(browser.baseUrl, () => {
|
||||
const stripQuery = (url: string) => url.replace(/\?.*$/, '');
|
||||
const stripTrailingSlash = (url: string) => url.replace(/\/$/, '');
|
||||
|
||||
beforeAll(done => page.init().then(done));
|
||||
beforeAll(() => page.init());
|
||||
|
||||
beforeEach(() => browser.waitForAngularEnabled(false));
|
||||
afterEach(() => browser.waitForAngularEnabled(true));
|
||||
|
||||
afterEach(async () => {
|
||||
await page.unregisterSw();
|
||||
await browser.waitForAngularEnabled(true);
|
||||
});
|
||||
|
||||
describe('(with sitemap URLs)', () => {
|
||||
page.sitemapUrls.forEach((path, i) => {
|
||||
@@ -34,7 +38,7 @@ describe(browser.baseUrl, () => {
|
||||
const actualUrl = await getCurrentUrl();
|
||||
|
||||
expect(actualUrl).toBe(expectedUrl);
|
||||
}, 60000);
|
||||
}, 120000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -38,19 +38,14 @@ export class SitePage {
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to a URL, disable animations, unregister the ServiceWorker, and wait for Angular.
|
||||
* Navigate to a URL, disable animations, wait for Angular and unregister the ServiceWorker.
|
||||
* (The SW is unregistered to ensure that subsequent requests are passed through to the server.)
|
||||
*/
|
||||
async goTo(url: string) {
|
||||
const unregisterServiceWorker = (cb: () => void) => navigator.serviceWorker
|
||||
.getRegistrations()
|
||||
.then(regs => Promise.all(regs.map(reg => reg.unregister())))
|
||||
.then(cb);
|
||||
|
||||
await browser.get(url || this.baseUrl);
|
||||
await browser.executeScript('document.body.classList.add(\'no-animations\')');
|
||||
await browser.executeAsyncScript(unregisterServiceWorker);
|
||||
await browser.waitForAngular();
|
||||
await this.unregisterSw();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -60,4 +55,16 @@ export class SitePage {
|
||||
// Make an initial request to unregister the ServiceWorker.
|
||||
await this.goTo('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the ServiceWorker (if registered).
|
||||
*/
|
||||
async unregisterSw() {
|
||||
const unregisterSwFn = (cb: () => void) => navigator.serviceWorker
|
||||
.getRegistrations()
|
||||
.then(regs => Promise.all(regs.map(reg => reg.unregister())))
|
||||
.then(cb);
|
||||
|
||||
await browser.executeAsyncScript(unregisterSwFn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,14 @@ import { SitePage } from './site.po';
|
||||
describe(browser.baseUrl, () => {
|
||||
const page = new SitePage();
|
||||
|
||||
beforeAll(done => page.init().then(done));
|
||||
beforeAll(() => page.init());
|
||||
|
||||
beforeEach(() => browser.waitForAngularEnabled(false));
|
||||
afterEach(() => browser.waitForAngularEnabled(true));
|
||||
|
||||
afterEach(async () => {
|
||||
await page.unregisterSw();
|
||||
await browser.waitForAngularEnabled(true);
|
||||
});
|
||||
|
||||
describe('(smoke tests)', () => {
|
||||
it('should show the home page', () => {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.9.0 <11.0.0",
|
||||
"yarn": ">=1.10.1 <1.13.0"
|
||||
"yarn": ">=1.10.1 <1.14.0"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
module.exports = function processCliCommands() {
|
||||
module.exports = function processCliCommands(createDocMessage) {
|
||||
return {
|
||||
$runAfter: ['extra-docs-added'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process(docs) {
|
||||
const navigationDoc = docs.find(doc => doc.docType === 'navigation-json');
|
||||
const navigationNode = navigationDoc && navigationDoc.data['SideNav'].find(node => node.title === 'CLI Commands');
|
||||
const navigationNode = navigationDoc && navigationDoc.data['SideNav'].find(node => node.children && node.children.length && node.children[0].url === 'cli');
|
||||
|
||||
if (!navigationNode) {
|
||||
throw new Error(createDocMessage('Missing `cli` url - CLI Commands must include a first child node with url set at `cli`', navigationDoc));
|
||||
}
|
||||
|
||||
docs.forEach(doc => {
|
||||
if (doc.docType === 'cli-command') {
|
||||
@@ -14,9 +18,7 @@ module.exports = function processCliCommands() {
|
||||
processOptions(doc, doc.options);
|
||||
|
||||
// Add to navigation doc
|
||||
if (navigationNode) {
|
||||
navigationNode.children.push({ url: doc.path, title: `ng ${doc.name}` });
|
||||
}
|
||||
navigationNode.children.push({ url: doc.path, title: `ng ${doc.name}` });
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -28,11 +30,6 @@ function processOptions(container, options) {
|
||||
container.namedOptions = [];
|
||||
|
||||
options.forEach(option => {
|
||||
|
||||
if (option.type === 'boolean' && option.default === undefined) {
|
||||
option.default = false;
|
||||
}
|
||||
|
||||
// Ignore any hidden options
|
||||
if (option.hidden) { return; }
|
||||
|
||||
|
||||
@@ -1,41 +1,51 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./processCliCommands');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('processCliCommands processor', () => {
|
||||
|
||||
let dgeni, injector, processor, createDocMessage;
|
||||
|
||||
const navigationStub = {
|
||||
docType: 'navigation-json',
|
||||
data: {
|
||||
SideNav: [{
|
||||
children: [{'url': 'cli'}]
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
dgeni = new Dgeni([testPackage('cli-docs-package')]);
|
||||
injector = dgeni.configureInjector();
|
||||
processor = injector.get('processCliCommands');
|
||||
createDocMessage = injector.get('createDocMessage');
|
||||
});
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('cli-docs-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('processCliCommands');
|
||||
expect(processor.$process).toBeDefined();
|
||||
});
|
||||
|
||||
it('should run after the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runAfter).toEqual(['extra-docs-added']);
|
||||
});
|
||||
|
||||
it('should run before the correct processor', () => {
|
||||
const processor = processorFactory();
|
||||
expect(processor.$runBefore).toEqual(['rendering-docs']);
|
||||
});
|
||||
|
||||
it('should collect the names (name + aliases)', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
commandAliases: ['alias1', 'alias2'],
|
||||
options: [],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.names).toEqual(['name', 'alias1', 'alias2']);
|
||||
});
|
||||
|
||||
describe('options', () => {
|
||||
it('should remove the hidden options', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -47,7 +57,7 @@ describe('processCliCommands processor', () => {
|
||||
{ name: 'option4', hidden: true },
|
||||
],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.namedOptions).toEqual([
|
||||
jasmine.objectContaining({ name: 'option1' }),
|
||||
jasmine.objectContaining({ name: 'option3' }),
|
||||
@@ -55,7 +65,6 @@ describe('processCliCommands processor', () => {
|
||||
});
|
||||
|
||||
it('should collect the non-hidden positional and named options', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -67,7 +76,7 @@ describe('processCliCommands processor', () => {
|
||||
{ name: 'positional2', hidden: true, positional: 1},
|
||||
],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.positionalOptions).toEqual([
|
||||
jasmine.objectContaining({ name: 'positional1', positional: 0}),
|
||||
]);
|
||||
@@ -77,7 +86,6 @@ describe('processCliCommands processor', () => {
|
||||
});
|
||||
|
||||
it('should sort the named options into order by name', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -88,7 +96,7 @@ describe('processCliCommands processor', () => {
|
||||
{ name: 'b' },
|
||||
],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.namedOptions).toEqual([
|
||||
jasmine.objectContaining({ name: 'a' }),
|
||||
jasmine.objectContaining({ name: 'b' }),
|
||||
@@ -99,7 +107,6 @@ describe('processCliCommands processor', () => {
|
||||
|
||||
describe('subcommands', () => {
|
||||
it('should convert subcommands hash into a collection', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -124,7 +131,7 @@ describe('processCliCommands processor', () => {
|
||||
},
|
||||
}],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.options[0].subcommands).toEqual([
|
||||
jasmine.objectContaining({ name: 'subcommand1' }),
|
||||
jasmine.objectContaining({ name: 'subcommand2' }),
|
||||
@@ -132,7 +139,6 @@ describe('processCliCommands processor', () => {
|
||||
});
|
||||
|
||||
it('should remove the hidden subcommand options', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -157,7 +163,7 @@ describe('processCliCommands processor', () => {
|
||||
},
|
||||
}],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.options[0].subcommands[0].namedOptions).toEqual([
|
||||
jasmine.objectContaining({ name: 'subcommand1-option1' }),
|
||||
]);
|
||||
@@ -167,7 +173,6 @@ describe('processCliCommands processor', () => {
|
||||
});
|
||||
|
||||
it('should collect the non-hidden positional arguments and named options', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -192,7 +197,7 @@ describe('processCliCommands processor', () => {
|
||||
},
|
||||
}],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.options[0].subcommands[0].positionalOptions).toEqual([
|
||||
jasmine.objectContaining({ name: 'subcommand1-option2', positional: 0}),
|
||||
]);
|
||||
@@ -205,7 +210,6 @@ describe('processCliCommands processor', () => {
|
||||
});
|
||||
|
||||
it('should sort the named subcommand options into order by name', () => {
|
||||
const processor = processorFactory();
|
||||
const doc = {
|
||||
docType: 'cli-command',
|
||||
name: 'name',
|
||||
@@ -224,7 +228,7 @@ describe('processCliCommands processor', () => {
|
||||
}
|
||||
}],
|
||||
};
|
||||
processor.$process([doc]);
|
||||
processor.$process([doc, navigationStub]);
|
||||
expect(doc.options[0].subcommands[0].namedOptions).toEqual([
|
||||
jasmine.objectContaining({ name: 'a' }),
|
||||
jasmine.objectContaining({ name: 'b' }),
|
||||
@@ -233,8 +237,7 @@ describe('processCliCommands processor', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should add the command to the CLI node in the navigation doc', () => {
|
||||
const processor = processorFactory();
|
||||
it('should add the command to the CLI node in the navigation doc if there is a first child node with a `cli` url', () => {
|
||||
const command = {
|
||||
docType: 'cli-command',
|
||||
name: 'command1',
|
||||
@@ -247,18 +250,55 @@ describe('processCliCommands processor', () => {
|
||||
data: {
|
||||
SideNav: [
|
||||
{ url: 'some/page', title: 'Some Page' },
|
||||
{ url: 'cli', title: 'CLI Commands', children: [
|
||||
{ url: 'cli', title: 'Using the CLI' },
|
||||
]},
|
||||
{ url: 'other/page', title: 'Other Page' },
|
||||
{
|
||||
title: 'CLI Commands',
|
||||
tooltip: 'Angular CLI command reference',
|
||||
children: [
|
||||
{
|
||||
'title': 'Overview',
|
||||
'url': 'cli'
|
||||
}
|
||||
]
|
||||
},
|
||||
{ url: 'other/page', title: 'Other Page' }
|
||||
]
|
||||
}
|
||||
};
|
||||
processor.$process([command, navigation]);
|
||||
expect(navigation.data.SideNav[1].title).toEqual('CLI Commands');
|
||||
expect(navigation.data.SideNav[1].children).toEqual([
|
||||
{ url: 'cli', title: 'Using the CLI' },
|
||||
{ url: 'cli', title: 'Overview' },
|
||||
{ url: 'cli/command1', title: 'ng command1' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should complain if there is no child with `cli` url', () => {
|
||||
const command = {
|
||||
docType: 'cli-command',
|
||||
name: 'command1',
|
||||
commandAliases: ['alias1', 'alias2'],
|
||||
options: [],
|
||||
path: 'cli/command1',
|
||||
};
|
||||
const navigation = {
|
||||
docType: 'navigation-json',
|
||||
data: {
|
||||
SideNav: [
|
||||
{ url: 'some/page', title: 'Some Page' },
|
||||
{
|
||||
title: 'CLI Commands',
|
||||
tooltip: 'Angular CLI command reference',
|
||||
children: [
|
||||
{
|
||||
'title': 'Overview',
|
||||
'url': 'client'
|
||||
}
|
||||
]
|
||||
},
|
||||
{ url: 'other/page', title: 'Other Page' }
|
||||
]
|
||||
}
|
||||
};
|
||||
expect(() => processor.$process([command, navigation])).toThrowError(createDocMessage('Missing `cli` url - CLI Commands must include a first child node with url set at `cli`', navigation));
|
||||
});
|
||||
});
|
||||
|
||||
+15
-12
@@ -798,9 +798,10 @@ anymatch@^2.0.0:
|
||||
micromatch "^3.1.4"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
app-root-path@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46"
|
||||
app-root-path@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a"
|
||||
integrity sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=
|
||||
|
||||
append-transform@^0.4.0:
|
||||
version "0.4.0"
|
||||
@@ -1976,16 +1977,17 @@ code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
|
||||
codelyzer@~4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.2.1.tgz#d56eaacefca7e8138aac0a630e484bdb09988544"
|
||||
codelyzer@~4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.5.0.tgz#a65ddeeeca2894653253a89bfa229118ff9f59b1"
|
||||
integrity sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==
|
||||
dependencies:
|
||||
app-root-path "^2.0.1"
|
||||
app-root-path "^2.1.0"
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
cssauron "^1.4.0"
|
||||
semver-dsl "^1.0.1"
|
||||
source-map "^0.5.6"
|
||||
sprintf-js "^1.0.3"
|
||||
source-map "^0.5.7"
|
||||
sprintf-js "^1.1.1"
|
||||
|
||||
coffee-script@^1.12.5:
|
||||
version "1.12.7"
|
||||
@@ -9291,9 +9293,10 @@ split-string@^3.0.1, split-string@^3.0.2:
|
||||
dependencies:
|
||||
extend-shallow "^3.0.0"
|
||||
|
||||
sprintf-js@^1.0.3:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
|
||||
sprintf-js@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
|
||||
integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
@@ -82,7 +82,7 @@
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"assets": [
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import { AppPage } from './app.po';
|
||||
import { browser } from 'protractor';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('Welcome to demo!');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
const logs = await browser.manage().logs().get('browser');
|
||||
expect(logs).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo() {
|
||||
return browser.get('/') as Promise<any>;
|
||||
}
|
||||
|
||||
getTitleText() {
|
||||
return element(by.css('app-root h1')).getText() as Promise<string>;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Demo</title>
|
||||
<base href="/">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
@@ -7,18 +7,12 @@ function testBazel() {
|
||||
bazel version
|
||||
rm -rf demo
|
||||
# Create project
|
||||
ng new demo --collection=@angular/bazel --defaults --skip-git
|
||||
ng new demo --collection=@angular/bazel --defaults --skip-git --style=scss
|
||||
node replace_angular_repo.js "./demo/WORKSPACE"
|
||||
cd demo
|
||||
# TODO(kyliau) Remove this once the type annotations are added to AppPage
|
||||
# https://github.com/angular/angular-cli/pull/13406
|
||||
cp ../app.po.ts ./e2e/src/
|
||||
cp ../package.json.replace ./package.json
|
||||
# Run build
|
||||
# TODO(kyliau): Use `bazel build` for now. Running `ng build` requires
|
||||
# node_modules to be available in project directory.
|
||||
bazel build //src:bundle
|
||||
# Run test
|
||||
ng generate component widget --style=css
|
||||
ng build
|
||||
ng test
|
||||
ng e2e
|
||||
}
|
||||
@@ -26,13 +20,7 @@ function testBazel() {
|
||||
function testNonBazel() {
|
||||
# Replace angular.json that uses Bazel builder with the default generated by CLI
|
||||
cp ../angular.json.original ./angular.json
|
||||
# TODO(kyliau) Remove this once the additional assertion is added to CLI
|
||||
cp ../app.e2e-spec.ts ./e2e/src/
|
||||
# TODO(kyliau) Remove this once web_package rule is in use
|
||||
cp ../index.html ./src/
|
||||
rm -rf dist src/main.dev.ts src/main.prod.ts
|
||||
# Just make a symlink instead of full yarn install to expose node_modules
|
||||
ln -s $(bazel info output_base)/external/npm/node_modules node_modules
|
||||
ng build --progress=false
|
||||
ng test --progress=false --watch=false
|
||||
ng e2e --configuration=ci
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@angular-devkit/architect@0.12.1":
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.12.1.tgz#397768d1ccd0cef76db96d6b39db8aebad68c031"
|
||||
integrity sha512-1ozBP0ZAApkSfuPpZ7b9vShU8smNxb98jW+65S12cPOxv1bVVxCj5sTmC3sSfXapgq/pMzblbaVSKOG7Ajz0vQ==
|
||||
"@angular-devkit/architect@0.13.0-rc.0":
|
||||
version "0.13.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.13.0-rc.0.tgz#d9bc43a3811f293269cf488539b72ce27afc6cdb"
|
||||
integrity sha512-abqtT5qyfTL29hf9be1MnaSVjIMJXJq+Oc+FZJ4RyQ+Sjs2zo+DjAJo62P1vS55JkLE1TFpEcjHkg118Cz7yOw==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.1"
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/architect@^0.10.6":
|
||||
@@ -40,12 +40,12 @@
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/core@7.2.1":
|
||||
version "7.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.2.1.tgz#8c6df59eab77bcc98a348c8cdf9eb217c8b751a5"
|
||||
integrity sha512-zOozPswSM1cTkltw5LeSPoZ/fJ2d3vN304IVgKgrM5/Fs54bd7nTaBcAK+HvjKS+5KmykYrXW47Q4CdFJikluQ==
|
||||
"@angular-devkit/core@7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.0-rc.0.tgz#e555a08d85259855ff1946f4268936a1aadd38f1"
|
||||
integrity sha512-0vHuw1gIMh79tI+gRxCMn89U1DnjmBnqybVktaf9YXi9xshxd+nnFb31v7n1tJQVQiQNzGxk3hviFnkzxLZipw==
|
||||
dependencies:
|
||||
ajv "6.6.2"
|
||||
ajv "6.7.0"
|
||||
chokidar "2.0.4"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
rxjs "6.3.3"
|
||||
@@ -59,16 +59,16 @@
|
||||
"@angular-devkit/core" "7.1.3"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@7.2.1":
|
||||
version "7.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.2.1.tgz#9c1c784f4a81a3a840fa4a1435948c6203be6062"
|
||||
integrity sha512-jEhwkeDn8exgJBfUwMc6rdtDkxHJkUmKPTn4M436bkMMMa9KFPFbPpzp9weKpB3SbRjM3Mu90JprO4C7qDtCcg==
|
||||
"@angular-devkit/schematics@7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.3.0-rc.0.tgz#9f1e1f6942da36b12c81241398ed6ca8b2e65875"
|
||||
integrity sha512-noqcQIOvah2G126DTFKY5Kiga8UwI9cKzyhQdNlf+8hAZpnWwTURItQ5xuMJg/XfRQLUSg9gWS2h1cI9AD7mxQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.1"
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular/bazel@file:../../dist/packages-dist/bazel":
|
||||
version "7.2.0"
|
||||
version "8.0.0-beta.0"
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "^0.10.6"
|
||||
"@angular-devkit/core" "^7.0.4"
|
||||
@@ -81,16 +81,20 @@
|
||||
tsickle "0.34.0"
|
||||
|
||||
"@angular/cli@file:../../node_modules/@angular/cli":
|
||||
version "7.2.1"
|
||||
version "7.3.0-rc.0"
|
||||
dependencies:
|
||||
"@angular-devkit/architect" "0.12.1"
|
||||
"@angular-devkit/core" "7.2.1"
|
||||
"@angular-devkit/schematics" "7.2.1"
|
||||
"@schematics/angular" "7.2.1"
|
||||
"@schematics/update" "0.12.1"
|
||||
"@angular-devkit/architect" "0.13.0-rc.0"
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
"@angular-devkit/schematics" "7.3.0-rc.0"
|
||||
"@schematics/angular" "7.3.0-rc.0"
|
||||
"@schematics/update" "0.13.0-rc.0"
|
||||
"@yarnpkg/lockfile" "1.1.0"
|
||||
ini "1.3.5"
|
||||
inquirer "6.2.1"
|
||||
opn "5.3.0"
|
||||
semver "5.5.1"
|
||||
npm-package-arg "6.1.0"
|
||||
opn "5.4.0"
|
||||
pacote "9.4.0"
|
||||
semver "5.6.0"
|
||||
symbol-observable "1.2.0"
|
||||
|
||||
"@bazel/bazel-darwin_x64@0.21.0":
|
||||
@@ -125,13 +129,13 @@
|
||||
source-map-support "0.5.9"
|
||||
tsutils "2.27.2"
|
||||
|
||||
"@schematics/angular@7.2.1":
|
||||
version "7.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.2.1.tgz#9eeab1354ec8d970121cc067e9636098ab84e152"
|
||||
integrity sha512-UdqU8udVr693BZ6uaZ7+el/VFlTjrmp56OS+6YaziyAko84e1Q1Fcx+fwdHugy4V3YmQhTVsyOPSEsphnwSwOA==
|
||||
"@schematics/angular@7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.3.0-rc.0.tgz#7519aa692dcaed63b9caa7d824846511905b1bfc"
|
||||
integrity sha512-yjCHgLSAqQKVZrZgf8F37cPQthhucIA10ofpIHPEZrvHwKBQhM9K3yfB7uYgkj4gzPTdREedb7Rm3/HY45L/1A==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.1"
|
||||
"@angular-devkit/schematics" "7.2.1"
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
"@angular-devkit/schematics" "7.3.0-rc.0"
|
||||
typescript "3.2.2"
|
||||
|
||||
"@schematics/angular@^7.0.4":
|
||||
@@ -143,18 +147,18 @@
|
||||
"@angular-devkit/schematics" "7.1.3"
|
||||
typescript "3.1.6"
|
||||
|
||||
"@schematics/update@0.12.1":
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.12.1.tgz#44d853321ae8a56c43a579c0639d26d625001037"
|
||||
integrity sha512-P92tDxy0AA1NPhaThiJ7fIFxIC4jzlGK7sJlpbnRREBImsI/O9gmGaV8Kjy+75vaEjqpWaU2oj1hnWqkmxSK1A==
|
||||
"@schematics/update@0.13.0-rc.0":
|
||||
version "0.13.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.13.0-rc.0.tgz#3d5bb6ce7d8d1ea44a0e0a644022bc655b80ae80"
|
||||
integrity sha512-XoU3TnaDcIFX7TU37bfjfAW0tI1tRD5DYQFHDBNOgS+78InGvR9+1CVzRJ4uWOjk0i+ZzDaGbYyR0iA47jSOTA==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.1"
|
||||
"@angular-devkit/schematics" "7.2.1"
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
"@angular-devkit/schematics" "7.3.0-rc.0"
|
||||
"@yarnpkg/lockfile" "1.1.0"
|
||||
ini "1.3.5"
|
||||
pacote "9.1.1"
|
||||
pacote "9.4.0"
|
||||
rxjs "6.3.3"
|
||||
semver "5.5.1"
|
||||
semver "5.6.0"
|
||||
semver-intersect "1.4.0"
|
||||
|
||||
"@types/node@6.0.84":
|
||||
@@ -204,10 +208,10 @@ ajv@6.5.3:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.6.2:
|
||||
version "6.6.2"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d"
|
||||
integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==
|
||||
ajv@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96"
|
||||
integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
@@ -328,7 +332,7 @@ binary-extensions@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14"
|
||||
integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==
|
||||
|
||||
bluebird@^3.5.1, bluebird@^3.5.2:
|
||||
bluebird@^3.5.1, bluebird@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
|
||||
integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==
|
||||
@@ -379,7 +383,7 @@ bytebuffer@~5:
|
||||
dependencies:
|
||||
long "~3"
|
||||
|
||||
cacache@^11.0.1, cacache@^11.2.0:
|
||||
cacache@^11.0.1:
|
||||
version "11.3.1"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f"
|
||||
integrity sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==
|
||||
@@ -399,6 +403,26 @@ cacache@^11.0.1, cacache@^11.2.0:
|
||||
unique-filename "^1.1.0"
|
||||
y18n "^4.0.0"
|
||||
|
||||
cacache@^11.3.2:
|
||||
version "11.3.2"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa"
|
||||
integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==
|
||||
dependencies:
|
||||
bluebird "^3.5.3"
|
||||
chownr "^1.1.1"
|
||||
figgy-pudding "^3.5.1"
|
||||
glob "^7.1.3"
|
||||
graceful-fs "^4.1.15"
|
||||
lru-cache "^5.1.1"
|
||||
mississippi "^3.0.0"
|
||||
mkdirp "^0.5.1"
|
||||
move-concurrently "^1.0.1"
|
||||
promise-inflight "^1.0.1"
|
||||
rimraf "^2.6.2"
|
||||
ssri "^6.0.1"
|
||||
unique-filename "^1.1.1"
|
||||
y18n "^4.0.0"
|
||||
|
||||
cache-base@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
|
||||
@@ -877,7 +901,7 @@ glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.2:
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2:
|
||||
version "4.1.15"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
|
||||
@@ -1260,6 +1284,13 @@ lru-cache@^4.1.2, lru-cache@^4.1.3:
|
||||
pseudomap "^1.0.2"
|
||||
yallist "^2.1.2"
|
||||
|
||||
lru-cache@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
||||
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
|
||||
dependencies:
|
||||
yallist "^3.0.2"
|
||||
|
||||
make-fetch-happen@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083"
|
||||
@@ -1489,7 +1520,7 @@ npm-bundled@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979"
|
||||
integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==
|
||||
|
||||
npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
|
||||
npm-package-arg@6.1.0, npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1"
|
||||
integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==
|
||||
@@ -1507,7 +1538,7 @@ npm-packlist@^1.1.12, npm-packlist@^1.1.6:
|
||||
ignore-walk "^3.0.1"
|
||||
npm-bundled "^1.0.1"
|
||||
|
||||
npm-pick-manifest@^2.1.0:
|
||||
npm-pick-manifest@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40"
|
||||
integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==
|
||||
@@ -1585,10 +1616,10 @@ onetime@^2.0.0:
|
||||
dependencies:
|
||||
mimic-fn "^1.0.0"
|
||||
|
||||
opn@5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c"
|
||||
integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==
|
||||
opn@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035"
|
||||
integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==
|
||||
dependencies:
|
||||
is-wsl "^1.1.0"
|
||||
|
||||
@@ -1622,17 +1653,17 @@ osenv@^0.1.4, osenv@^0.1.5:
|
||||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.0"
|
||||
|
||||
pacote@9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.1.1.tgz#25091f75a25021de8be8d34cc6408728fca3579b"
|
||||
integrity sha512-f28Rq5ozzKAA9YwIKw61/ipwAatUZseYmVssDbHHaexF0wRIVotapVEZPAjOT7Eu3LYVqEp0NVpNizoAnYBUaA==
|
||||
pacote@9.4.0:
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.4.0.tgz#af979abdeb175cd347c3e33be3241af1ed254807"
|
||||
integrity sha512-WQ1KL/phGMkedYEQx9ODsjj7xvwLSpdFJJdEXrLyw5SILMxcTNt5DTxT2Z93fXuLFYJBlZJdnwdalrQdB/rX5w==
|
||||
dependencies:
|
||||
bluebird "^3.5.2"
|
||||
cacache "^11.2.0"
|
||||
bluebird "^3.5.3"
|
||||
cacache "^11.3.2"
|
||||
figgy-pudding "^3.5.1"
|
||||
get-stream "^4.1.0"
|
||||
glob "^7.1.3"
|
||||
lru-cache "^4.1.3"
|
||||
lru-cache "^5.1.1"
|
||||
make-fetch-happen "^4.0.1"
|
||||
minimatch "^3.0.4"
|
||||
minipass "^2.3.5"
|
||||
@@ -1641,7 +1672,7 @@ pacote@9.1.1:
|
||||
normalize-package-data "^2.4.0"
|
||||
npm-package-arg "^6.1.0"
|
||||
npm-packlist "^1.1.12"
|
||||
npm-pick-manifest "^2.1.0"
|
||||
npm-pick-manifest "^2.2.3"
|
||||
npm-registry-fetch "^3.8.0"
|
||||
osenv "^0.1.5"
|
||||
promise-inflight "^1.0.1"
|
||||
@@ -1651,7 +1682,7 @@ pacote@9.1.1:
|
||||
safe-buffer "^5.1.2"
|
||||
semver "^5.6.0"
|
||||
ssri "^6.0.1"
|
||||
tar "^4.4.6"
|
||||
tar "^4.4.8"
|
||||
unique-filename "^1.1.1"
|
||||
which "^1.3.1"
|
||||
|
||||
@@ -1913,11 +1944,6 @@ semver-intersect@1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
|
||||
|
||||
semver@5.5.1:
|
||||
version "5.5.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
|
||||
integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==
|
||||
|
||||
set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
@@ -2170,7 +2196,7 @@ symbol-observable@1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
|
||||
|
||||
tar@^4, tar@^4.4.6:
|
||||
tar@^4, tar@^4.4.8:
|
||||
version "4.4.8"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
|
||||
integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==
|
||||
|
||||
@@ -37,9 +37,14 @@ ts_devserver(
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "rollup_bundle")
|
||||
|
||||
filegroup(
|
||||
name = "empty_node_modules",
|
||||
)
|
||||
|
||||
rollup_bundle(
|
||||
name = "bundle",
|
||||
entry_point = "src/main",
|
||||
node_modules = ":empty_node_modules",
|
||||
deps = ["//src"],
|
||||
)
|
||||
|
||||
|
||||
+16
-16
@@ -2,24 +2,24 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@bazel/bazel-darwin_x64@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.18.0.tgz#bab437605a702279d42f59caa4741bb327eb7dbc"
|
||||
integrity sha512-um2OzgLL2Gd/W6joOpvrSTcqpnupliPNpwe/uE7sB0huBSJ/4Im0w2IlCTI6C7OfgMcbpUj4YxgUa9T6u6WY6w==
|
||||
"@bazel/bazel-darwin_x64@0.20.0":
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.20.0.tgz#648d61c32a3c5fccb7bf70b753071b6e54b11f21"
|
||||
integrity sha512-zeoeVK504341GfnaxdaB4pFzQV0YOK1HLiYj3/ocamPFxAJRh9abvKB8iOpqD5Oal0j7VsINxnXCjovp9a4urA==
|
||||
|
||||
"@bazel/bazel-linux_x64@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.18.0.tgz#0c02b2404ec95c180e17615cc7079ee07df48a69"
|
||||
integrity sha512-Rq8X8bL6SgQvbOHnfPhSgF6hp+f6Fbt2w6pRmBlFvV1J+CeUyrSrrRXfnnO1bjIuq05Ur3mV8ULA0qK6rtA5lQ==
|
||||
"@bazel/bazel-linux_x64@0.20.0":
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.20.0.tgz#2568628a0d0b85dcc69d0ab701b1d6e10551357d"
|
||||
integrity sha512-PpHzoEqfXty8dc1/p1tVFXtbPyrE1n0N79QmYePjJ5mJMyW7uBF/zV4IajYY8+IpJEcDVq5v4BavSexOmVJRmA==
|
||||
|
||||
"@bazel/bazel-win32_x64@0.18.0":
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.18.0.tgz#aa4575fb00066dcf59a6d464971774dea6a0bafd"
|
||||
integrity sha512-U2TbfK8B7dc3JqXSFwj2oXCQrxEaSzCCUkAHjAOIGOKzx/HLKIKs+NJj9IQkLLr7BsMU+Qqzo8aqo11E+Vs+aA==
|
||||
"@bazel/bazel-win32_x64@0.20.0":
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.20.0.tgz#af7d041dae4c066e7aa8618949e2de1aad07495e"
|
||||
integrity sha512-3bqHXFBvLnbvNzr1KCQ1zryTYvHMoQffaWVekbckgPyT2VPEj3abuB91+DrRYmZdPjcgPYnjnyanxZHDkKuF2g==
|
||||
|
||||
"@bazel/bazel@file:../../node_modules/@bazel/bazel":
|
||||
version "0.18.0"
|
||||
version "0.20.0"
|
||||
optionalDependencies:
|
||||
"@bazel/bazel-darwin_x64" "0.18.0"
|
||||
"@bazel/bazel-linux_x64" "0.18.0"
|
||||
"@bazel/bazel-win32_x64" "0.18.0"
|
||||
"@bazel/bazel-darwin_x64" "0.20.0"
|
||||
"@bazel/bazel-linux_x64" "0.20.0"
|
||||
"@bazel/bazel-win32_x64" "0.20.0"
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "7.2.2",
|
||||
"version": "7.2.3",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
@@ -9,7 +9,7 @@
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.9.0 <11.0.0",
|
||||
"yarn": ">=1.10.1 <1.13.0"
|
||||
"yarn": ">=1.10.1 <1.14.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -34,7 +34,7 @@
|
||||
"@angular-devkit/architect": "^0.10.6",
|
||||
"@angular-devkit/build-optimizer": "^0.12.2",
|
||||
"@angular-devkit/core": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.3.0-rc.0",
|
||||
"@bazel/karma": "~0.22.1",
|
||||
"@bazel/typescript": "~0.22.1",
|
||||
"@schematics/angular": "^7.0.4",
|
||||
@@ -94,8 +94,8 @@
|
||||
"// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.",
|
||||
"// 3": "when updating @bazel/bazel version you also need to update the RBE settings in .bazelrc (see https://github.com/angular/angular/pull/27935)",
|
||||
"devDependencies": {
|
||||
"@angular/cli": "^7.2.1",
|
||||
"@bazel/bazel": "~0.21.0",
|
||||
"@angular/cli": "^7.3.0-rc.0",
|
||||
"@bazel/bazel": "~0.22.0",
|
||||
"@bazel/buildifier": "^0.19.2",
|
||||
"@bazel/ibazel": "~0.9.0",
|
||||
"@types/angular": "^1.6.47",
|
||||
@@ -135,7 +135,7 @@
|
||||
"rewire": "2.5.2",
|
||||
"rollup-plugin-commonjs": "8.1.0",
|
||||
"rxjs": "^6.3.0",
|
||||
"sauce-connect": "https://saucelabs.com/downloads/sc-4.5.2-linux.tar.gz",
|
||||
"sauce-connect": "https://saucelabs.com/downloads/sc-4.5.3-linux.tar.gz",
|
||||
"semver": "5.4.1",
|
||||
"systemjs": "0.18.10",
|
||||
"tslint": "5.7.0",
|
||||
|
||||
@@ -10,7 +10,6 @@ ng_module(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/animations",
|
||||
deps = [
|
||||
"//packages/core",
|
||||
],
|
||||
@@ -30,6 +29,7 @@ ng_package(
|
||||
# Do not add more to this list.
|
||||
# Dependencies on the full npm_package cause long re-builds.
|
||||
visibility = [
|
||||
"//packages/compiler-cli/integrationtest:__pkg__",
|
||||
"//packages/compiler/test:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
|
||||
@@ -12,7 +12,6 @@ ng_module(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/animations/browser",
|
||||
deps = [
|
||||
"//packages/animations",
|
||||
"//packages/core",
|
||||
|
||||
@@ -26,7 +26,7 @@ const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g');
|
||||
*
|
||||
* 1. Overlap of animations
|
||||
* Given that a CSS property cannot be animated in more than one place at the same time, it's
|
||||
* important that this behaviour is detected and validated. The way in which this occurs is that
|
||||
* important that this behavior is detected and validated. The way in which this occurs is that
|
||||
* each time a style property is examined, a string-map containing the property will be updated with
|
||||
* the start and end times for when the property is used within an animation step.
|
||||
*
|
||||
|
||||
@@ -7,7 +7,6 @@ load("//tools:defaults.bzl", "ng_module")
|
||||
ng_module(
|
||||
name = "testing",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
module_name = "@angular/animations/browser/testing",
|
||||
deps = [
|
||||
"//packages/animations",
|
||||
"//packages/animations/browser",
|
||||
|
||||
@@ -671,8 +671,8 @@ export function animate(
|
||||
*
|
||||
* ```typescript
|
||||
* group([
|
||||
* animate("1s", { background: "black" }))
|
||||
* animate("2s", { color: "white" }))
|
||||
* animate("1s", style({ background: "black" })),
|
||||
* animate("2s", style({ color: "white" }))
|
||||
* ])
|
||||
* ```
|
||||
*
|
||||
@@ -708,7 +708,7 @@ export function group(
|
||||
* ```typescript
|
||||
* sequence([
|
||||
* style({ opacity: 0 })),
|
||||
* animate("1s", { opacity: 1 }))
|
||||
* animate("1s", style({ opacity: 1 }))
|
||||
* ])
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"dependencies": {
|
||||
"@angular-devkit/architect": "^0.10.6",
|
||||
"@angular-devkit/core": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.0.4",
|
||||
"@angular-devkit/schematics": "^7.3.0-rc.0",
|
||||
"@bazel/typescript": "^0.22.1",
|
||||
"@schematics/angular": "^7.0.4",
|
||||
"@types/node": "6.0.84",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
/// <reference types='node'/>
|
||||
import {spawn, spawnSync} from 'child_process';
|
||||
import {join} from 'path';
|
||||
import {Observable, Subject} from 'rxjs';
|
||||
|
||||
export type Executable = 'bazel' | 'ibazel';
|
||||
@@ -17,7 +18,8 @@ export function runBazel(
|
||||
projectDir: string, executable: Executable, command: Command, workspaceTarget: string,
|
||||
flags: string[]): Observable<void> {
|
||||
const doneSubject = new Subject<void>();
|
||||
const buildProcess = spawn(executable, [command, workspaceTarget, ...flags], {
|
||||
const bin = join(projectDir, 'node_modules', '.bin', executable);
|
||||
const buildProcess = spawn(bin, [command, workspaceTarget, ...flags], {
|
||||
cwd: projectDir,
|
||||
stdio: 'inherit',
|
||||
shell: false,
|
||||
@@ -35,7 +37,8 @@ export function runBazel(
|
||||
}
|
||||
|
||||
export function checkInstallation(executable: Executable, projectDir: string) {
|
||||
const child = spawnSync(executable, ['version'], {
|
||||
const bin = join(projectDir, 'node_modules', '.bin', executable);
|
||||
const child = spawnSync(bin, ['version'], {
|
||||
cwd: projectDir,
|
||||
shell: false,
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import {BuildEvent, Builder, BuilderConfiguration, BuilderContext} from '@angular-devkit/architect';
|
||||
import {getSystemPath, resolve} from '@angular-devkit/core';
|
||||
import {Observable, of } from 'rxjs';
|
||||
import {catchError, map, tap} from 'rxjs/operators';
|
||||
import {catchError, map} from 'rxjs/operators';
|
||||
|
||||
import {checkInstallation, runBazel} from './bazel';
|
||||
import {Schema} from './schema';
|
||||
@@ -28,7 +28,8 @@ class BazelBuilder implements Builder<Schema> {
|
||||
if (!checkInstallation(executable, projectRoot)) {
|
||||
throw new Error(
|
||||
`Could not run ${executable}. Please make sure that the ` +
|
||||
`"${executable}" command is available in the $PATH.`);
|
||||
`"${executable}" command is installed by running ` +
|
||||
`"npm install" or "yarn install".`);
|
||||
}
|
||||
|
||||
// TODO: Support passing flags.
|
||||
|
||||
@@ -136,15 +136,13 @@ if (process.env['WEB_TEST_METADATA']) {
|
||||
}
|
||||
setConf(conf, 'directConnect', true, 'is set to true for chrome');
|
||||
setConf(conf, 'chromeDriver', chromeDriver, 'is determined by the browsers attribute');
|
||||
mergeCapabilities(
|
||||
conf, {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: {
|
||||
binary: chromeBin,
|
||||
args: args,
|
||||
}
|
||||
},
|
||||
'is determined by the browsers attribute');
|
||||
mergeCapabilities(conf, {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: {
|
||||
binary: chromeBin,
|
||||
args: args,
|
||||
}
|
||||
});
|
||||
}
|
||||
if (webTestNamedFiles['FIREFOX']) {
|
||||
// TODO(gmagolan): implement firefox support for protractor
|
||||
|
||||
@@ -12,6 +12,7 @@ ts_library(
|
||||
"@npm//@types/node",
|
||||
"@npm//jasmine",
|
||||
"@npm//protractor",
|
||||
"@npm//tslib",
|
||||
],
|
||||
data = [
|
||||
"//:tsconfig.json",
|
||||
|
||||
@@ -21,21 +21,15 @@ import {Schema as BazelWorkspaceOptions} from './schema';
|
||||
* Look for package.json file for package with `packageName` in node_modules and
|
||||
* extract its version.
|
||||
*/
|
||||
function findVersion(projectName: string, packageName: string, host: Tree): string|null {
|
||||
// Need to look in multiple locations because we could be working in a subtree.
|
||||
const candidates = [
|
||||
`node_modules/${packageName}/package.json`,
|
||||
`${projectName}/node_modules/${packageName}/package.json`,
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (host.exists(candidate)) {
|
||||
try {
|
||||
const packageJson = JSON.parse(host.read(candidate).toString());
|
||||
if (packageJson.name === packageName && packageJson.version) {
|
||||
return packageJson.version;
|
||||
}
|
||||
} catch {
|
||||
function findVersion(packageName: string, host: Tree): string|null {
|
||||
const candidate = `node_modules/${packageName}/package.json`;
|
||||
if (host.exists(candidate)) {
|
||||
try {
|
||||
const packageJson = JSON.parse(host.read(candidate).toString());
|
||||
if (packageJson.name === packageName && packageJson.version) {
|
||||
return packageJson.version;
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -72,23 +66,17 @@ function hasSassStylesheet(host: Tree) {
|
||||
|
||||
export default function(options: BazelWorkspaceOptions): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
if (!options.name) {
|
||||
throw new SchematicsException(`Invalid options, "name" is required.`);
|
||||
const name = options.name || getWorkspace(host).defaultProject;
|
||||
if (!name) {
|
||||
throw new Error('Please provide a name for Bazel workspace');
|
||||
}
|
||||
validateProjectName(options.name);
|
||||
let newProjectRoot = '';
|
||||
try {
|
||||
const workspace = getWorkspace(host);
|
||||
newProjectRoot = workspace.newProjectRoot || '';
|
||||
} catch {
|
||||
}
|
||||
const appDir = `${newProjectRoot}/${options.name}`;
|
||||
validateProjectName(name);
|
||||
|
||||
// If the project already has some deps installed, Bazel should use existing
|
||||
// versions.
|
||||
const existingVersions = {
|
||||
Angular: findVersion(options.name, '@angular/core', host),
|
||||
RxJs: findVersion(options.name, 'rxjs', host),
|
||||
Angular: findVersion('@angular/core', host),
|
||||
RxJs: findVersion('rxjs', host),
|
||||
};
|
||||
|
||||
Object.keys(existingVersions).forEach((name: 'Angular' | 'RxJs') => {
|
||||
@@ -110,12 +98,11 @@ export default function(options: BazelWorkspaceOptions): Rule {
|
||||
return mergeWith(apply(url('./files'), [
|
||||
applyTemplates({
|
||||
utils: strings,
|
||||
...options,
|
||||
name,
|
||||
'dot': '.', ...workspaceVersions,
|
||||
routing: hasRoutingModule(host),
|
||||
sass: hasSassStylesheet(host),
|
||||
}),
|
||||
move(appDir),
|
||||
]));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,24 +21,24 @@ describe('Bazel-workspace Schematic', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
const files = host.files;
|
||||
expect(files).toContain('/demo/.bazelignore');
|
||||
expect(files).toContain('/demo/.bazelrc');
|
||||
expect(files).toContain('/demo/BUILD.bazel');
|
||||
expect(files).toContain('/demo/src/BUILD.bazel');
|
||||
expect(files).toContain('/demo/WORKSPACE');
|
||||
expect(files).toContain('/demo/yarn.lock');
|
||||
expect(files).toContain('/.bazelignore');
|
||||
expect(files).toContain('/.bazelrc');
|
||||
expect(files).toContain('/BUILD.bazel');
|
||||
expect(files).toContain('/src/BUILD.bazel');
|
||||
expect(files).toContain('/WORKSPACE');
|
||||
expect(files).toContain('/yarn.lock');
|
||||
});
|
||||
|
||||
it('should find existing Angular version', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
host.create('/demo/node_modules/@angular/core/package.json', JSON.stringify({
|
||||
host.create('/node_modules/@angular/core/package.json', JSON.stringify({
|
||||
name: '@angular/core',
|
||||
version: '6.6.6',
|
||||
}));
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
const workspace = host.readContent('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const workspace = host.readContent('/WORKSPACE');
|
||||
expect(workspace).toMatch('ANGULAR_VERSION = "6.6.6"');
|
||||
});
|
||||
|
||||
@@ -46,19 +46,19 @@ describe('Bazel-workspace Schematic', () => {
|
||||
const options = {...defaultOptions, name: 'demo-app'};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
const {files} = host;
|
||||
expect(files).toContain('/demo-app/src/BUILD.bazel');
|
||||
const content = host.readContent('/demo-app/src/BUILD.bazel');
|
||||
expect(files).toContain('/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain('entry_module = "demo_app/src/main.dev"');
|
||||
});
|
||||
|
||||
it('should add router if project contains routing module', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
host.create('/demo/src/app/app-routing.module.ts', '');
|
||||
expect(host.files).toContain('/demo/src/app/app-routing.module.ts');
|
||||
host.create('/src/app/app-routing.module.ts', '');
|
||||
expect(host.files).toContain('/src/app/app-routing.module.ts');
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/src/BUILD.bazel');
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
expect(host.files).toContain('/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain('@angular//packages/router');
|
||||
});
|
||||
|
||||
@@ -66,16 +66,16 @@ describe('Bazel-workspace Schematic', () => {
|
||||
it('should contain project name', () => {
|
||||
const options = {...defaultOptions};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain('workspace(name = "demo")');
|
||||
});
|
||||
|
||||
it('should convert dashes in name to underscore', () => {
|
||||
const options = {...defaultOptions, name: 'demo-project'};
|
||||
const host = schematicRunner.runSchematic('bazel-workspace', options);
|
||||
expect(host.files).toContain('/demo-project/WORKSPACE');
|
||||
const content = host.readContent('/demo-project/WORKSPACE');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain('workspace(name = "demo_project"');
|
||||
});
|
||||
});
|
||||
@@ -83,40 +83,25 @@ describe('Bazel-workspace Schematic', () => {
|
||||
describe('SASS', () => {
|
||||
let host = new UnitTestTree(new HostTree);
|
||||
beforeAll(() => {
|
||||
host.create('/demo/src/app/app.component.scss', '');
|
||||
expect(host.files).toContain('/demo/src/app/app.component.scss');
|
||||
host.create('/src/app/app.component.scss', '');
|
||||
expect(host.files).toContain('/src/app/app.component.scss');
|
||||
const options = {...defaultOptions};
|
||||
host = schematicRunner.runSchematic('bazel-workspace', options, host);
|
||||
expect(host.files).toContain('/demo/WORKSPACE');
|
||||
expect(host.files).toContain('/demo/src/BUILD.bazel');
|
||||
expect(host.files).toContain('/WORKSPACE');
|
||||
expect(host.files).toContain('/src/BUILD.bazel');
|
||||
});
|
||||
|
||||
it('should download rules_sass in WORKSPACE', () => {
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
it('should download and load rules_sass in WORKSPACE', () => {
|
||||
const content = host.readContent('/WORKSPACE');
|
||||
expect(content).toContain('RULES_SASS_VERSION');
|
||||
expect(content).toContain('io_bazel_rules_sass');
|
||||
});
|
||||
|
||||
it('should load sass_repositories in WORKSPACE', () => {
|
||||
const content = host.readContent('/demo/WORKSPACE');
|
||||
expect(content).toContain(
|
||||
'load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")');
|
||||
expect(content).toContain('sass_repositories()');
|
||||
});
|
||||
|
||||
it('should add sass_binary rules in src/BUILD', () => {
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
const content = host.readContent('/src/BUILD.bazel');
|
||||
expect(content).toContain('load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")');
|
||||
expect(content).toMatch(/sass_binary\((.*\n)+\)/);
|
||||
});
|
||||
|
||||
it('should add SASS targets to assets of ng_module in src/BUILD', () => {
|
||||
const content = host.readContent('/demo/src/BUILD.bazel');
|
||||
expect(content).toContain(`
|
||||
assets = glob([
|
||||
"**/*.css",
|
||||
"**/*.html",
|
||||
]) + [":style_" + x for x in glob(["**/*.scss"])],`);
|
||||
expect(content).toContain('glob(["**/*.scss"])');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,5 +9,5 @@ export interface Schema {
|
||||
/**
|
||||
* The name of the project.
|
||||
*/
|
||||
name: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,5 @@
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -201,13 +201,16 @@ export default function(options: Schema): Rule {
|
||||
validateProjectName(options.name);
|
||||
|
||||
return chain([
|
||||
externalSchematic('@schematics/angular', 'ng-new', {
|
||||
...options,
|
||||
skipInstall: true,
|
||||
}),
|
||||
externalSchematic(
|
||||
'@schematics/angular', 'ng-new',
|
||||
{
|
||||
...options,
|
||||
}),
|
||||
addDevDependenciesToPackageJson(options),
|
||||
addDevAndProdMainForAot(options),
|
||||
schematic('bazel-workspace', options),
|
||||
schematic('bazel-workspace', options, {
|
||||
scope: options.name,
|
||||
}),
|
||||
overwriteGitignore(options),
|
||||
updateWorkspaceFileToUseBazelBuilder(options),
|
||||
]);
|
||||
|
||||
@@ -32,7 +32,18 @@
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@7.1.2", "@angular-devkit/schematics@^7.0.4":
|
||||
"@angular-devkit/core@7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.3.0-rc.0.tgz#e555a08d85259855ff1946f4268936a1aadd38f1"
|
||||
integrity sha512-0vHuw1gIMh79tI+gRxCMn89U1DnjmBnqybVktaf9YXi9xshxd+nnFb31v7n1tJQVQiQNzGxk3hviFnkzxLZipw==
|
||||
dependencies:
|
||||
ajv "6.7.0"
|
||||
chokidar "2.0.4"
|
||||
fast-json-stable-stringify "2.0.0"
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/schematics@7.1.2":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.1.2.tgz#847639044417d044bf1bc87f64508a0c3f99fae2"
|
||||
integrity sha512-NFhHLYWf9gpGQm0s19lq+nAw3CZ0udBpoBLzCm8Crlmu6+7aAXgw7Fv5P4ukWJ/e1m7NDGVids+B6kBGXaY6Ig==
|
||||
@@ -40,6 +51,14 @@
|
||||
"@angular-devkit/core" "7.1.2"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@^7.3.0-rc.0":
|
||||
version "7.3.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.3.0-rc.0.tgz#9f1e1f6942da36b12c81241398ed6ca8b2e65875"
|
||||
integrity sha512-noqcQIOvah2G126DTFKY5Kiga8UwI9cKzyhQdNlf+8hAZpnWwTURItQ5xuMJg/XfRQLUSg9gWS2h1cI9AD7mxQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.3.0-rc.0"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@bazel/typescript@^0.22.1":
|
||||
version "0.22.1"
|
||||
resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-0.22.1.tgz#b52c00e8560019e2f9d273d45c04785e0ec9d9bd"
|
||||
@@ -79,6 +98,16 @@ ajv@6.5.3:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96"
|
||||
integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
|
||||
@@ -10,7 +10,6 @@ ts_library(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/benchpress",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
|
||||
@@ -10,7 +10,6 @@ ng_module(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/common",
|
||||
deps = [
|
||||
"//packages/core",
|
||||
"@rxjs",
|
||||
@@ -34,6 +33,7 @@ ng_package(
|
||||
# Dependencies on the full npm_package cause long re-builds.
|
||||
visibility = [
|
||||
"//packages/bazel/test/ng_package:__pkg__",
|
||||
"//packages/compiler-cli/integrationtest:__pkg__",
|
||||
"//packages/compiler-cli/test:__pkg__",
|
||||
"//packages/compiler-cli/test/diagnostics:__pkg__",
|
||||
"//packages/compiler-cli/test/ngcc:__pkg__",
|
||||
|
||||
@@ -12,7 +12,6 @@ ng_module(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/common/http",
|
||||
deps = [
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
|
||||
@@ -12,7 +12,6 @@ ng_module(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/common/http/testing",
|
||||
deps = [
|
||||
"//packages/common/http",
|
||||
"//packages/core",
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
["**/*.ts"],
|
||||
exclude = ["closure-locale.ts"],
|
||||
),
|
||||
module_name = "@angular/common/locales",
|
||||
)
|
||||
|
||||
npm_package(
|
||||
|
||||
@@ -26,15 +26,61 @@ export class NgForOfContext<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `NgForOf` directive instantiates a template once per item from an iterable. The context
|
||||
* for each instantiated template inherits from the outer context with the given loop variable
|
||||
* set to the current item from the iterable.
|
||||
* A [structural directive](guide/structural-directives) that renders
|
||||
* a template for each item in a collection.
|
||||
* The directive is placed on an element, which becomes the parent
|
||||
* of the cloned templates.
|
||||
*
|
||||
* The `ngForOf` is generally used in the
|
||||
* [shorthand form](guide/structural-directives#the-asterisk--prefix) `*ngFor`.
|
||||
* In this form, the template to be rendered for each iteration is the content
|
||||
* of an anchor element containing the directive.
|
||||
*
|
||||
* The following example shows the shorthand syntax with some options,
|
||||
* contained in an `<li>` element.
|
||||
*
|
||||
* ```
|
||||
* <li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>
|
||||
* ```
|
||||
*
|
||||
* The shorthand form expands into a long form that uses the `ngForOf` selector
|
||||
* on an `<ng-template>` element.
|
||||
* The content of the `<ng-template>` element is the `<li>` element that held the
|
||||
* short-form directive.
|
||||
*
|
||||
* Here is the expanded version of the short-form example.
|
||||
*
|
||||
* ```
|
||||
* <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
|
||||
* <li>...</li>
|
||||
* </ng-template>
|
||||
* ```
|
||||
*
|
||||
* Angular automatically expands the shorthand syntax as it compiles the template.
|
||||
* The context for each embedded view is logically merged to the current component
|
||||
* context according to its lexical position.
|
||||
*
|
||||
* When using the shorthand syntax, Angular allows only [one structural directive
|
||||
* on an element](guide/structural-directives#one-structural-directive-per-host-element).
|
||||
* If you want to iterate conditionally, for example,
|
||||
* put the `*ngIf` on a container element that wraps the `*ngFor` element.
|
||||
* For futher discussion, see
|
||||
* [Structural Directives](guide/structural-directives#one-per-element).
|
||||
*
|
||||
* @usageNotes
|
||||
*
|
||||
* ### Local Variables
|
||||
* ### Local variables
|
||||
*
|
||||
* `NgForOf` provides several exported values that can be aliased to local variables:
|
||||
* `NgForOf` provides exported values that can be aliased to local variables.
|
||||
* For example:
|
||||
*
|
||||
* ```
|
||||
* <li *ngFor="let user of userObservable | async as users; index as i; first as isFirst">
|
||||
* {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
|
||||
* </li>
|
||||
* ```
|
||||
*
|
||||
* The following exported values can be aliased to local variables:
|
||||
*
|
||||
* - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
|
||||
* - `ngForOf: NgIterable<T>`: The value of the iterable expression. Useful when the expression is
|
||||
@@ -46,55 +92,33 @@ export class NgForOfContext<T> {
|
||||
* - `even: boolean`: True when the item has an even index in the iterable.
|
||||
* - `odd: boolean`: True when the item has an odd index in the iterable.
|
||||
*
|
||||
* ```
|
||||
* <li *ngFor="let user of userObservable | async as users; index as i; first as isFirst">
|
||||
* {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
|
||||
* </li>
|
||||
* ```
|
||||
*
|
||||
* ### Change Propagation
|
||||
* ### Change propagation
|
||||
*
|
||||
* When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:
|
||||
*
|
||||
* * When an item is added, a new instance of the template is added to the DOM.
|
||||
* * When an item is removed, its template instance is removed from the DOM.
|
||||
* * When items are reordered, their respective templates are reordered in the DOM.
|
||||
* * Otherwise, the DOM element for that item will remain the same.
|
||||
*
|
||||
* Angular uses object identity to track insertions and deletions within the iterator and reproduce
|
||||
* those changes in the DOM. This has important implications for animations and any stateful
|
||||
* controls (such as `<input>` elements which accept user input) that are present. Inserted rows can
|
||||
* controls that are present, such as `<input>` elements that accept user input. Inserted rows can
|
||||
* be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state
|
||||
* such as user input.
|
||||
* For more on animations, see [Transitions and Triggers](guide/transition-and-triggers).
|
||||
*
|
||||
* It is possible for the identities of elements in the iterator to change while the data does not.
|
||||
* This can happen, for example, if the iterator produced from an RPC to the server, and that
|
||||
* RPC is re-run. Even if the data hasn't changed, the second response will produce objects with
|
||||
* different identities, and Angular will tear down the entire DOM and rebuild it (as if all old
|
||||
* elements were deleted and all new elements inserted). This is an expensive operation and should
|
||||
* be avoided if possible.
|
||||
* The identities of elements in the iterator can change while the data does not.
|
||||
* This can happen, for example, if the iterator is produced from an RPC to the server, and that
|
||||
* RPC is re-run. Even if the data hasn't changed, the second response produces objects with
|
||||
* different identities, and Angular must tear down the entire DOM and rebuild it (as if all old
|
||||
* elements were deleted and all new elements inserted).
|
||||
*
|
||||
* To customize the default tracking algorithm, `NgForOf` supports `trackBy` option.
|
||||
* `trackBy` takes a function which has two arguments: `index` and `item`.
|
||||
* To avoid this expensive operation, you can customize the default tracking algorithm.
|
||||
* by supplying the `trackBy` option to `NgForOf`.
|
||||
* `trackBy` takes a function that has two arguments: `index` and `item`.
|
||||
* If `trackBy` is given, Angular tracks changes by the return value of the function.
|
||||
*
|
||||
* ### Syntax
|
||||
*
|
||||
* - `<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>`
|
||||
*
|
||||
* With `<ng-template>` element:
|
||||
*
|
||||
* ```
|
||||
* <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn">
|
||||
* <li>...</li>
|
||||
* </ng-template>
|
||||
* ```
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* See a [live demo](http://plnkr.co/edit/KVuXxDp0qinGDyo307QW?p=preview) for a more detailed
|
||||
* example.
|
||||
*
|
||||
* @see [Structural Directives](guide/structural-directives)
|
||||
* @ngModule CommonModule
|
||||
* @publicApi
|
||||
*/
|
||||
@@ -204,9 +228,9 @@ export class NgForOf<T> implements DoCheck {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the correct type of the context for the template that `NgForOf` will render.
|
||||
* Asserts the correct type of the context for the template that `NgForOf` will render.
|
||||
*
|
||||
* The presence of this method is a signal to the Ivy template type check compiler that the
|
||||
* The presence of this method is a signal to the Ivy template type-check compiler that the
|
||||
* `NgForOf` structural directive renders its template with a specific context type.
|
||||
*/
|
||||
static ngTemplateContextGuard<T>(dir: NgForOf<T>, ctx: any): ctx is NgForOfContext<T> {
|
||||
|
||||
@@ -10,94 +10,140 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, ɵstri
|
||||
|
||||
|
||||
/**
|
||||
* Conditionally includes a template based on the value of an `expression`.
|
||||
* A structural directive that conditionally includes a template based on the value of
|
||||
* an expression coerced to Boolean.
|
||||
* When the expression evaluates to true, Angular renders the template
|
||||
* provided in a `then` clause, and when false or null,
|
||||
* Angular renders the template provided in an optional `else` clause. The default
|
||||
* template for the `else` clause is blank.
|
||||
*
|
||||
* `ngIf` evaluates the `expression` and then renders the `then` or `else` template in its place
|
||||
* when expression is truthy or falsy respectively. Typically the:
|
||||
* - `then` template is the inline template of `ngIf` unless bound to a different value.
|
||||
* - `else` template is blank unless it is bound.
|
||||
* A [shorthand form](guide/structural-directives#the-asterisk--prefix) of the directive,
|
||||
* `*ngIf="condition"`, is generally used, provided
|
||||
* as an attribute of the anchor element for the inserted template.
|
||||
* Angular expands this into a more explicit version, in which the anchor element
|
||||
* is contained in an `<ng-template>` element.
|
||||
*
|
||||
* Simple form with shorthand syntax:
|
||||
*
|
||||
* ```
|
||||
* <div *ngIf="condition">Content to render when condition is true.</div>
|
||||
* ```
|
||||
*
|
||||
* Simple form with expanded syntax:
|
||||
*
|
||||
* ```
|
||||
* <ng-template [ngIf]="condition"><div>Content to render when condition is
|
||||
* true.</div></ng-template>
|
||||
* ```
|
||||
*
|
||||
* Form with an "else" block:
|
||||
*
|
||||
* ```
|
||||
* <div *ngIf="condition; else elseBlock">Content to render when condition is true.</div>
|
||||
* <ng-template #elseBlock>Content to render when condition is false.</ng-template>
|
||||
* ```
|
||||
*
|
||||
* Shorthand form with "then" and "else" blocks:
|
||||
*
|
||||
* ```
|
||||
* <div *ngIf="condition; then thenBlock else elseBlock"></div>
|
||||
* <ng-template #thenBlock>Content to render when condition is true.</ng-template>
|
||||
* <ng-template #elseBlock>Content to render when condition is false.</ng-template>
|
||||
* ```
|
||||
*
|
||||
* Form with storing the value locally:
|
||||
*
|
||||
* ```
|
||||
* <div *ngIf="condition as value; else elseBlock">{{value}}</div>
|
||||
* <ng-template #elseBlock>Content to render when value is null.</ng-template>
|
||||
* ```
|
||||
*
|
||||
* @usageNotes
|
||||
*
|
||||
* ### Most common usage
|
||||
* The `*ngIf` directive is most commonly used to conditionally show an inline template,
|
||||
* as seen in the following example.
|
||||
* The default `else` template is blank.
|
||||
*
|
||||
* The most common usage of the `ngIf` directive is to conditionally show the inline template as
|
||||
* seen in this example:
|
||||
* {@example common/ngIf/ts/module.ts region='NgIfSimple'}
|
||||
*
|
||||
* ### Showing an alternative template using `else`
|
||||
*
|
||||
* If it is necessary to display a template when the `expression` is falsy use the `else` template
|
||||
* binding as shown. Note that the `else` binding points to a `<ng-template>` labeled `#elseBlock`.
|
||||
* The template can be defined anywhere in the component view but is typically placed right after
|
||||
* To display a template when `expression` evaluates to false, use an `else` template
|
||||
* binding as shown in the following example.
|
||||
* The `else` binding points to an `<ng-template>` element labeled `#elseBlock`.
|
||||
* The template can be defined anywhere in the component view, but is typically placed right after
|
||||
* `ngIf` for readability.
|
||||
*
|
||||
* {@example common/ngIf/ts/module.ts region='NgIfElse'}
|
||||
*
|
||||
* ### Using non-inlined `then` template
|
||||
* ### Using an external `then` template
|
||||
*
|
||||
* Usually the `then` template is the inlined template of the `ngIf`, but it can be changed using
|
||||
* a binding (just like `else`). Because `then` and `else` are bindings, the template references can
|
||||
* change at runtime as shown in this example.
|
||||
* In the previous example, the then-clause template is specified inline, as the content of the
|
||||
* tag that contains the `ngIf` directive. You can also specify a template that is defined
|
||||
* externally, by referencing a labeled `<ng-template>` element. When you do this, you can
|
||||
* change which template to use at runtime, as shown in the following example.
|
||||
*
|
||||
* {@example common/ngIf/ts/module.ts region='NgIfThenElse'}
|
||||
*
|
||||
* ### Storing conditional result in a variable
|
||||
* ### Storing a conditional result in a variable
|
||||
*
|
||||
* A common pattern is that we need to show a set of properties from the same object. If the
|
||||
* object is undefined, then we have to use the safe-traversal-operator `?.` to guard against
|
||||
* dereferencing a `null` value. This is especially the case when waiting on async data such as
|
||||
* when using the `async` pipe as shown in following example:
|
||||
*
|
||||
* ```
|
||||
* Hello {{ (userStream|async)?.last }}, {{ (userStream|async)?.first }}!
|
||||
* ```
|
||||
*
|
||||
* There are several inefficiencies in the above example:
|
||||
* - We create multiple subscriptions on `userStream`. One for each `async` pipe, or two in the
|
||||
* example above.
|
||||
* - We cannot display an alternative screen while waiting for the data to arrive asynchronously.
|
||||
* - We have to use the safe-traversal-operator `?.` to access properties, which is cumbersome.
|
||||
* - We have to place the `async` pipe in parenthesis.
|
||||
*
|
||||
* A better way to do this is to use `ngIf` and store the result of the condition in a local
|
||||
* variable as shown in the the example below:
|
||||
* You might want to show a set of properties from the same object. If you are waiting
|
||||
* for asynchronous data, the object can be undefined.
|
||||
* In this case, you can use `ngIf` and store the result of the condition in a local
|
||||
* variable as shown in the the following example.
|
||||
*
|
||||
* {@example common/ngIf/ts/module.ts region='NgIfAs'}
|
||||
*
|
||||
* Notice that:
|
||||
* - We use only one `async` pipe and hence only one subscription gets created.
|
||||
* - `ngIf` stores the result of the `userStream|async` in the local variable `user`.
|
||||
* - The local `user` can then be bound repeatedly in a more efficient way.
|
||||
* - No need to use the safe-traversal-operator `?.` to access properties as `ngIf` will only
|
||||
* display the data if `userStream` returns a value.
|
||||
* - We can display an alternative template while waiting for the data.
|
||||
* This code uses only one `AsyncPipe`, so only one subscription is created.
|
||||
* The conditional statement stores the result of `userStream|async` in the local variable `user`.
|
||||
* You can then bind the local `user` repeatedly.
|
||||
*
|
||||
* ### Syntax
|
||||
* The conditional displays the data only if `userStream` returns a value,
|
||||
* so you don't need to use the
|
||||
* [safe-navigation-operator](guide/template-syntax#safe-navigation-operator) (`?.`)
|
||||
* to guard against null values when accessing properties.
|
||||
* You can display an alternative template while waiting for the data.
|
||||
*
|
||||
* Simple form:
|
||||
* - `<div *ngIf="condition">...</div>`
|
||||
* - `<ng-template [ngIf]="condition"><div>...</div></ng-template>`
|
||||
* ### Shorthand syntax
|
||||
*
|
||||
* The shorthand syntax `*ngIf` expands into two separate template specifications
|
||||
* for the "then" and "else" clauses. For example, consider the following shorthand statement,
|
||||
* that is meant to show a loading page while waiting for data to be loaded.
|
||||
*
|
||||
* Form with an else block:
|
||||
* ```
|
||||
* <div *ngIf="condition; else elseBlock">...</div>
|
||||
* <ng-template #elseBlock>...</ng-template>
|
||||
* <div class="hero-list" *ngIf="heroes else loading">
|
||||
* ...
|
||||
* </div>
|
||||
*
|
||||
* <ng-template #loading>
|
||||
* <div>Loading...</div>
|
||||
* </ng-template>
|
||||
* ```
|
||||
*
|
||||
* Form with a `then` and `else` block:
|
||||
* You can see that the "else" clause references the `<ng-template>`
|
||||
* with the `#loading` label, and the template for the "then" clause
|
||||
* is provided as the content of the anchor element.
|
||||
*
|
||||
* However, when Angular expands the shorthand syntax, it creates
|
||||
* another `<ng-template>` tag, with `ngIf` and `ngIfElse` directives.
|
||||
* The anchor element containing the template for the "then" clause becomes
|
||||
* the content of this unlabeled `<ng-template>` tag.
|
||||
*
|
||||
* ```
|
||||
* <div *ngIf="condition; then thenBlock else elseBlock"></div>
|
||||
* <ng-template #thenBlock>...</ng-template>
|
||||
* <ng-template #elseBlock>...</ng-template>
|
||||
* <ng-template [ngIf]="hero-list" [ngIfElse]="loading">
|
||||
* <div class="hero-list">
|
||||
* ...
|
||||
* </div>
|
||||
* </ng-template>
|
||||
*
|
||||
* <ng-template #loading>
|
||||
* <div>Loading...</div>
|
||||
* </ng-template>
|
||||
* ```
|
||||
*
|
||||
* Form with storing the value locally:
|
||||
* ```
|
||||
* <div *ngIf="condition as value; else elseBlock">{{value}}</div>
|
||||
* <ng-template #elseBlock>...</ng-template>
|
||||
* ```
|
||||
* The presence of the implicit template object has implications for the nesting of
|
||||
* structural directives. For more on this subject, see
|
||||
* [Structural Directives](https://angular.io/guide/structural-directives#one-per-element).
|
||||
*
|
||||
* @ngModule CommonModule
|
||||
* @publicApi
|
||||
|
||||
@@ -7,7 +7,6 @@ load("//tools:defaults.bzl", "ng_module")
|
||||
ng_module(
|
||||
name = "testing",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
module_name = "@angular/common/testing",
|
||||
deps = [
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
|
||||
@@ -20,7 +20,6 @@ ts_library(
|
||||
"src/integrationtest/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/compiler-cli",
|
||||
tsconfig = ":tsconfig",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
@@ -48,7 +47,9 @@ npm_package(
|
||||
],
|
||||
# Do not add more to this list.
|
||||
# Dependencies on the full npm_package cause long re-builds.
|
||||
visibility = ["//visibility:private"],
|
||||
visibility = [
|
||||
"//packages/compiler-cli/integrationtest:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":compiler-cli",
|
||||
"//packages/compiler-cli/src/ngcc",
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
# Legacy docs for @angular/compiler-cli Developers
|
||||
|
||||
*Note from Igor: This doc is likely outdated now but I'm keeping it around because
|
||||
offline_compiler_test.sh need to be converted to bazel/circleci (or deleted) and these docs seem
|
||||
relevant to anyone who needs to understand those tests. Once that's done this file can be deleted.*
|
||||
|
||||
|
||||
```
|
||||
# Build Angular and the compiler
|
||||
./build.sh
|
||||
|
||||
# Run the test once
|
||||
# (First edit the LINKABLE_PKGS to use npm link instead of npm install)
|
||||
$ ./scripts/ci/offline_compiler_test.sh
|
||||
|
||||
# Keep a package fresh in watch mode
|
||||
./node_modules/.bin/tsc -p packages/compiler/tsconfig-build.json -w
|
||||
|
||||
# Recompile @angular/core module (needs to use tsc-ext to keep the metadata)
|
||||
$ export NODE_PATH=${NODE_PATH}:$(pwd)/dist/all:$(pwd)/dist/tools
|
||||
$ node dist/tools/@angular/compiler-cli/src/main -p packages/core/tsconfig-build.json
|
||||
|
||||
# Iterate on the test
|
||||
$ cd /tmp/wherever/e2e_test.1464388257/
|
||||
$ ./node_modules/.bin/ngc
|
||||
$ ./node_modules/.bin/jasmine test/*_spec.js
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_test")
|
||||
load("//tools:defaults.bzl", "nodejs_binary")
|
||||
|
||||
nodejs_binary(
|
||||
name = "ngc_bin",
|
||||
data = [
|
||||
"//packages/compiler-cli",
|
||||
"@ngdeps//chokidar",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
entry_point = "angular/packages/compiler-cli/src/main.js",
|
||||
)
|
||||
|
||||
nodejs_binary(
|
||||
name = "ng_xi18n",
|
||||
data = [
|
||||
"//packages/compiler-cli",
|
||||
"@ngdeps//chokidar",
|
||||
"@ngdeps//reflect-metadata",
|
||||
],
|
||||
entry_point = "angular/packages/compiler-cli/src/extract_i18n.js",
|
||||
)
|
||||
|
||||
nodejs_test(
|
||||
name = "integrationtest",
|
||||
data = [
|
||||
":ngc_bin",
|
||||
":ng_xi18n",
|
||||
"@nodejs//:node",
|
||||
"@ngdeps//domino",
|
||||
"@ngdeps//chokidar",
|
||||
"@ngdeps//source-map-support",
|
||||
"@ngdeps//shelljs",
|
||||
"@ngdeps//typescript",
|
||||
"@ngdeps//reflect-metadata",
|
||||
"@ngdeps//rxjs",
|
||||
"@ngdeps//tslib",
|
||||
"@ngdeps//jasmine/bin:jasmine",
|
||||
"@ngdeps//zone.js",
|
||||
"@ngdeps//xhr2",
|
||||
"@ngdeps//@types/node",
|
||||
"@ngdeps//@types/jasmine",
|
||||
"//packages/animations:npm_package",
|
||||
"//packages/common:npm_package",
|
||||
"//packages/compiler:npm_package",
|
||||
"//packages/compiler-cli:npm_package",
|
||||
"//packages/core:npm_package",
|
||||
"//packages/forms:npm_package",
|
||||
"//packages/http:npm_package",
|
||||
"//packages/platform-browser:npm_package",
|
||||
"//packages/platform-browser-dynamic:npm_package",
|
||||
"//packages/platform-server:npm_package",
|
||||
"//packages/router:npm_package",
|
||||
] + glob(["**/*"]),
|
||||
entry_point = "angular/packages/compiler-cli/integrationtest/test.js",
|
||||
tags = ["no-ivy-aot"],
|
||||
)
|
||||
@@ -1,26 +1,21 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": "ng",
|
||||
"flatModuleId": "flat_module",
|
||||
"flatModuleOutFile": "index.js",
|
||||
"skipTemplateCodegen": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "../node_modules/flat_module",
|
||||
// Prevent scanning up the directory tree for types
|
||||
"typeRoots": ["node_modules/@types"]
|
||||
"rootDir": "",
|
||||
"target": "es5"
|
||||
},
|
||||
|
||||
"files": ["public-api.ts"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"debug": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"baseUrl": ".",
|
||||
// don't auto-discover @types/fs-extra
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"rootDir": "",
|
||||
"target": "es5",
|
||||
"types": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
<target>tervetuloa</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
|
||||
<source>other-3rdP-component</source>
|
||||
<target>other-3rdP-component</target>
|
||||
<source>other-3rdP-component
|
||||
multi-lines</source>
|
||||
<target>other-3rdP-component
|
||||
multi-lines</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
</xliff>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import {ApplicationRef, NgModule, forwardRef} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {MATERIAL_SANITY_CHECKS, MdButtonModule} from '@angular/material';
|
||||
import {ServerModule} from '@angular/platform-server';
|
||||
import {FlatModule} from 'flat_module';
|
||||
// Note: don't refer to third_party_src as we want to test that
|
||||
@@ -60,7 +59,6 @@ export {SomeModule as JitSummariesSomeModule} from './jit_summaries';
|
||||
imports: [
|
||||
ServerModule,
|
||||
FormsModule,
|
||||
MdButtonModule,
|
||||
ModuleUsingCustomElements,
|
||||
SomeLibModule.withProviders(),
|
||||
ThirdpartyModule,
|
||||
@@ -69,9 +67,6 @@ export {SomeModule as JitSummariesSomeModule} from './jit_summaries';
|
||||
providers: [
|
||||
SomeService,
|
||||
{provide: CUSTOM, useValue: forwardRef(() => ({name: 'some name'}))},
|
||||
// disable sanity check for material because it throws an error when used server-side
|
||||
// see https://github.com/angular/material2/issues/6292
|
||||
{provide: MATERIAL_SANITY_CHECKS, useValue: false},
|
||||
],
|
||||
entryComponents: [
|
||||
AnimateCmp,
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const shx = require('shelljs');
|
||||
const os = require('os');
|
||||
const {runCommand, setupTestDirectory} = require('./test_helpers');
|
||||
|
||||
const ngcBin = require.resolve('./ngc_bin');
|
||||
const xi18nBin = require.resolve('./ng_xi18n');
|
||||
const nodeBin = require.resolve(`nodejs/bin/node${(os.platform() === 'win32' ? '.cmd' : '')}`);
|
||||
const jasmineBin = require.resolve('ngdeps/node_modules/jasmine/bin/jasmine.js');
|
||||
|
||||
// Prepare the test directory before building the integration test output. This ensures that
|
||||
// the test runs in an hermetic way and works on Windows.
|
||||
const tmpDir = setupTestDirectory();
|
||||
|
||||
// Compile the "flat_module" Angular project using NGC.
|
||||
runCommand(ngcBin, ['-p', 'flat_module/tsconfig-build.json']);
|
||||
|
||||
// Copy HTML asset files from the "flat_module" package to the NPM output. The "flat_module"
|
||||
// has template code generation disabled and therefore needs to have the asset files included
|
||||
// next to the JavaScript output.
|
||||
shx.cp(
|
||||
path.join(tmpDir, 'flat_module/src/*.html'), path.join(tmpDir, 'node_modules/flat_module/src'));
|
||||
|
||||
// Compile the "third_party" Angular project using NGC.
|
||||
runCommand(ngcBin, ['-p', 'third_party_src/tsconfig-build.json']);
|
||||
|
||||
// Compile the main integration-test Angular project using NGC. Also uses a translated
|
||||
// i18n file which will be used to verify the translated templates of components.
|
||||
runCommand(ngcBin, [
|
||||
'-p', 'tsconfig-build.json', '--i18nFile=src/messages.fi.xlf', '--locale=fi', '--i18nFormat=xlf'
|
||||
]);
|
||||
|
||||
// Extract the i18n messages into various formats that will be verified
|
||||
// later on by the "i18n_spec" within "test/".
|
||||
runCommand(xi18nBin, ['-p', 'tsconfig-xi18n.json', '--i18nFormat=xlf', '--locale=fr']);
|
||||
runCommand(
|
||||
xi18nBin, ['-p', 'tsconfig-xi18n.json', '--i18nFormat=xlf2', '--outFile=messages.xliff2.xlf']);
|
||||
runCommand(
|
||||
xi18nBin, ['-p', 'tsconfig-xi18n.json', '--i18nFormat=xmb', '--outFile=custom_file.xmb']);
|
||||
|
||||
// Run the ngtools tests that verify that the public API provided by the "compiler-cli"
|
||||
// is working as expected in real projects.
|
||||
runCommand(nodeBin, [path.join(tmpDir, 'test/test_ngtools_api.js')]);
|
||||
|
||||
// Run all specs which verify the output from the previously built modules and i18n files.
|
||||
runCommand(nodeBin, [jasmineBin, path.join(tmpDir, 'test/all_spec.js')]);
|
||||
@@ -16,10 +16,12 @@ import {createComponent} from './util';
|
||||
describe('template codegen output', () => {
|
||||
const outDir = 'src';
|
||||
|
||||
it('should lower Decorators without reflect-metadata', () => {
|
||||
const jsOutput = path.join(outDir, 'basic.js');
|
||||
expect(fs.existsSync(jsOutput)).toBeTruthy();
|
||||
expect(fs.readFileSync(jsOutput, {encoding: 'utf-8'})).not.toContain('Reflect.decorate');
|
||||
it('should be able to lower annotations as static fields', () => {
|
||||
const basicFilePath = path.join(outDir, 'basic.js');
|
||||
expect(fs.existsSync(basicFilePath)).toBeTruthy();
|
||||
const fileContent = fs.readFileSync(basicFilePath, 'utf8');
|
||||
expect(fileContent).not.toContain('Reflect.decorate');
|
||||
expect(fileContent).toContain('BasicComp.decorators = [');
|
||||
});
|
||||
|
||||
it('should produce metadata.json outputs', () => {
|
||||
|
||||
@@ -36,8 +36,8 @@ const EXPECTED_XMB = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<messagebundle>
|
||||
<msg id="126808141597411718"><source>node_modules/third_party/other_comp.d.ts:1,2</source>other-3rdP-component
|
||||
multi-lines</msg>
|
||||
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/basic.ts:1</source>translate me</msg>
|
||||
<msg id="3492007542396725315"><source>src/basic.ts:5</source><source>src/entry_components.ts:1</source>Welcome</msg>
|
||||
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/basic.html:1</source>translate me</msg>
|
||||
<msg id="3492007542396725315"><source>src/basic.html:5</source><source>src/entry_components.ts:1</source>Welcome</msg>
|
||||
</messagebundle>
|
||||
`;
|
||||
|
||||
@@ -56,7 +56,7 @@ multi-lines</source>
|
||||
<trans-unit id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" datatype="html">
|
||||
<source>translate me</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/basic.ts</context>
|
||||
<context context-type="sourcefile">src/basic.html</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">desc</note>
|
||||
@@ -65,7 +65,7 @@ multi-lines</source>
|
||||
<trans-unit id="65cc4ab3b4c438e07c89be2b677d08369fb62da2" datatype="html">
|
||||
<source>Welcome</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/basic.ts</context>
|
||||
<context context-type="sourcefile">src/basic.html</context>
|
||||
<context context-type="linenumber">5</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
@@ -94,7 +94,7 @@ multi-lines</source>
|
||||
<notes>
|
||||
<note category="description">desc</note>
|
||||
<note category="meaning">meaning</note>
|
||||
<note category="location">src/basic.ts:1</note>
|
||||
<note category="location">src/basic.html:1</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translate me</source>
|
||||
@@ -102,7 +102,7 @@ multi-lines</source>
|
||||
</unit>
|
||||
<unit id="3492007542396725315">
|
||||
<notes>
|
||||
<note category="location">src/basic.ts:5</note>
|
||||
<note category="location">src/basic.html:5</note>
|
||||
<note category="location">src/entry_components.ts:1</note>
|
||||
</notes>
|
||||
<segment>
|
||||
@@ -114,31 +114,31 @@ multi-lines</source>
|
||||
`;
|
||||
|
||||
describe('template i18n extraction output', () => {
|
||||
const outDir = 'out';
|
||||
const outputDir = path.join(__dirname, '../xi18n-out');
|
||||
|
||||
it('should extract i18n messages as xmb', () => {
|
||||
const xmbOutput = path.join(outDir, 'custom_file.xmb');
|
||||
const xmbOutput = path.join(outputDir, 'custom_file.xmb');
|
||||
expect(fs.existsSync(xmbOutput)).toBeTruthy();
|
||||
const xmb = fs.readFileSync(xmbOutput, {encoding: 'utf-8'});
|
||||
expect(xmb).toEqual(EXPECTED_XMB);
|
||||
});
|
||||
|
||||
it('should extract i18n messages as xliff', () => {
|
||||
const xlfOutput = path.join(outDir, 'messages.xlf');
|
||||
const xlfOutput = path.join(outputDir, 'messages.xlf');
|
||||
expect(fs.existsSync(xlfOutput)).toBeTruthy();
|
||||
const xlf = fs.readFileSync(xlfOutput, {encoding: 'utf-8'});
|
||||
expect(xlf).toEqual(EXPECTED_XLIFF);
|
||||
});
|
||||
|
||||
it('should extract i18n messages as xliff version 2.0', () => {
|
||||
const xlfOutput = path.join(outDir, 'messages.xliff2.xlf');
|
||||
const xlfOutput = path.join(outputDir, 'messages.xliff2.xlf');
|
||||
expect(fs.existsSync(xlfOutput)).toBeTruthy();
|
||||
const xlf = fs.readFileSync(xlfOutput, {encoding: 'utf-8'});
|
||||
expect(xlf).toEqual(EXPECTED_XLIFF2);
|
||||
});
|
||||
|
||||
it('should not emit js', () => {
|
||||
const files = fs.readdirSync(outDir);
|
||||
const files = fs.readdirSync(outputDir);
|
||||
files.forEach(f => expect(f).not.toMatch(/\.js$/));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'reflect-metadata';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import * as assert from 'assert';
|
||||
import {__NGTOOLS_PRIVATE_API_2, readConfiguration} from '@angular/compiler-cli';
|
||||
import {createProgram, readConfiguration} from '@angular/compiler-cli';
|
||||
|
||||
/* tslint:disable:no-console */
|
||||
/**
|
||||
@@ -22,19 +22,10 @@ import {__NGTOOLS_PRIVATE_API_2, readConfiguration} from '@angular/compiler-cli'
|
||||
* properly read and wrote.
|
||||
*/
|
||||
function main() {
|
||||
console.log(`testing ngtools API...`);
|
||||
|
||||
Promise.resolve()
|
||||
.then(() => lazyRoutesTest())
|
||||
.then(() => {
|
||||
console.log('All done!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err.stack);
|
||||
console.error('Test failed');
|
||||
process.exit(1);
|
||||
});
|
||||
Promise.resolve().then(() => lazyRoutesTest()).then(() => { process.exit(0); }).catch((err) => {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
function lazyRoutesTest() {
|
||||
@@ -43,13 +34,15 @@ function lazyRoutesTest() {
|
||||
|
||||
const config = readConfiguration(project);
|
||||
const host = ts.createCompilerHost(config.options, true);
|
||||
const program = ts.createProgram(config.rootNames, config.options, host);
|
||||
const program = createProgram({
|
||||
rootNames: config.rootNames,
|
||||
options: config.options, host,
|
||||
});
|
||||
|
||||
config.options.basePath = basePath;
|
||||
config.options.rootDir = basePath;
|
||||
|
||||
const lazyRoutes = __NGTOOLS_PRIVATE_API_2.listLazyRoutes(
|
||||
{program, host, angularCompilerOptions: config.options, entryModule: 'app.module#AppModule'});
|
||||
|
||||
const lazyRoutes = program.listLazyRoutes('app.module#AppModule');
|
||||
const expectations: {[route: string]: string} = {
|
||||
'./lazy.module#LazyModule': 'lazy.module.ts',
|
||||
'./feature/feature.module#FeatureModule': 'feature/feature.module.ts',
|
||||
@@ -61,17 +54,25 @@ function lazyRoutesTest() {
|
||||
'feature/feature.module#FeatureModule': 'feature/feature.module.ts'
|
||||
};
|
||||
|
||||
Object.keys(lazyRoutes).forEach((route: string) => {
|
||||
assert(route in expectations, `Found a route that was not expected: "${route}".`);
|
||||
lazyRoutes.forEach(lazyRoute => {
|
||||
const routeName = lazyRoute.route;
|
||||
|
||||
// Normalize the module path and the expected module path so that these can be compared
|
||||
// on Windows where path separators are not consistent with TypeScript internal paths.
|
||||
const modulePath = path.normalize(lazyRoute.referencedModule.filePath);
|
||||
const expectedModulePath = path.normalize(path.join(basePath, expectations[routeName]));
|
||||
|
||||
assert(routeName in expectations, `Found a route that was not expected: "${routeName}".`);
|
||||
assert(
|
||||
lazyRoutes[route] == path.join(basePath, expectations[route]),
|
||||
`Route "${route}" does not point to the expected absolute path ` +
|
||||
`"${path.join(basePath, expectations[route])}". It points to "${lazyRoutes[route]}"`);
|
||||
modulePath === expectedModulePath,
|
||||
`Route "${routeName}" does not point to the expected absolute path ` +
|
||||
`"${expectedModulePath}". It points to "${modulePath}"`);
|
||||
});
|
||||
|
||||
// Verify that all expectations were met.
|
||||
assert.deepEqual(
|
||||
Object.keys(lazyRoutes), Object.keys(expectations), `Expected routes listed to be: \n` +
|
||||
lazyRoutes.map(lazyRoute => lazyRoute.route), Object.keys(expectations),
|
||||
`Expected routes listed to be: \n` +
|
||||
` ${JSON.stringify(Object.keys(expectations))}\n` +
|
||||
`Actual:\n` +
|
||||
` ${JSON.stringify(Object.keys(lazyRoutes))}\n`);
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
const child_process = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const shx = require('shelljs');
|
||||
|
||||
/** Manifest path that refers to the Bazel package that contains all test sources. */
|
||||
const baseManifestPath = 'angular/packages/compiler-cli/integrationtest';
|
||||
|
||||
/**
|
||||
* Temporary directory which will be used to build and run the integration tests. Note that
|
||||
* this environment variable is automatically set by Bazel for such test actions.
|
||||
*/
|
||||
const tmpDir = process.env.TEST_TMPDIR;
|
||||
|
||||
/** Fine grained node modules which are required in order to run the integration test. */
|
||||
const requiredNodeModules = {
|
||||
'@angular/animations': resolveNpmTreeArtifact('angular/packages/animations/npm_package'),
|
||||
'@angular/common': resolveNpmTreeArtifact('angular/packages/common/npm_package'),
|
||||
'@angular/compiler': resolveNpmTreeArtifact('angular/packages/compiler/npm_package'),
|
||||
'@angular/compiler-cli': resolveNpmTreeArtifact('angular/packages/compiler-cli/npm_package'),
|
||||
'@angular/core': resolveNpmTreeArtifact('angular/packages/core/npm_package'),
|
||||
'@angular/forms': resolveNpmTreeArtifact('angular/packages/forms/npm_package'),
|
||||
'@angular/http': resolveNpmTreeArtifact('angular/packages/http/npm_package'),
|
||||
'@angular/platform-browser':
|
||||
resolveNpmTreeArtifact('angular/packages/platform-browser/npm_package'),
|
||||
'@angular/platform-browser-dynamic':
|
||||
resolveNpmTreeArtifact('angular/packages/platform-browser-dynamic/npm_package'),
|
||||
'@angular/platform-server':
|
||||
resolveNpmTreeArtifact('angular/packages/platform-server/npm_package'),
|
||||
'@angular/router': resolveNpmTreeArtifact('angular/packages/router/npm_package'),
|
||||
'@types/jasmine': resolveNpmTreeArtifact('ngdeps/node_modules/@types/jasmine'),
|
||||
'@types/node': resolveNpmTreeArtifact('ngdeps/node_modules/@types/node'),
|
||||
|
||||
// Transitive dependencies which need to be specified because the Angular NPM packages
|
||||
// depend on these without the Angular NPM packages being part of the Bazel managed deps.
|
||||
// This means that transitive dependencies need to be manually declared as required.
|
||||
'tslib': resolveNpmTreeArtifact('ngdeps/node_modules/tslib'),
|
||||
'domino': resolveNpmTreeArtifact('ngdeps/node_modules/domino'),
|
||||
'xhr2': resolveNpmTreeArtifact('ngdeps/node_modules/xhr2'),
|
||||
|
||||
// Fine grained dependencies which are used by the integration test Angular modules, and
|
||||
// need to be symlinked so that they can be resolved by NodeJS or NGC.
|
||||
'reflect-metadata': resolveNpmTreeArtifact('ngdeps/node_modules/reflect-metadata'),
|
||||
'rxjs': resolveNpmTreeArtifact('ngdeps/node_modules/rxjs'),
|
||||
'source-map-support': resolveNpmTreeArtifact('ngdeps/node_modules/source-map-support'),
|
||||
'typescript': resolveNpmTreeArtifact('ngdeps/node_modules/typescript'),
|
||||
'zone.js': resolveNpmTreeArtifact('ngdeps/node_modules/zone.js'),
|
||||
};
|
||||
|
||||
/** Sets up the temporary test directory and returns the path to the directory. */
|
||||
exports.setupTestDirectory = function() {
|
||||
copySourceFilesToTempDir();
|
||||
symlinkNodeModules();
|
||||
return tmpDir;
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs a given binary with the specified command line arguments. The working directory for
|
||||
* the spawned process will be the temporary directory.
|
||||
*/
|
||||
exports.runCommand = function runCommand(binary, args = []) {
|
||||
const ngcProcess = child_process.spawnSync(binary, args, {
|
||||
stdio: 'inherit',
|
||||
cwd: tmpDir,
|
||||
env: {
|
||||
...process.env,
|
||||
// We need to set the "NODE_PATH" here because the built Angular NPM packages are symlinks
|
||||
// which NodeJS resolves into the output location. This is problematic because the output
|
||||
// location does not have the required dependencies of these NPM packages installed. This
|
||||
// could be fixed by setting the NodeJS "--preserve-symlinks" option, but this would mean
|
||||
// that transitive dependencies of fine-grained dependencies cannot be resolved either.
|
||||
NODE_PATH: path.join(tmpDir, 'node_modules/')
|
||||
}
|
||||
});
|
||||
|
||||
if (ngcProcess.status !== 0) {
|
||||
console.error(`Command ${binary} failed with arguments: "${args.join(' ')}". See error above.`);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Symlinks the specified node modules within the temporary directory. This is necessary because
|
||||
* this test is an integration test and we don't want to rely on any path-mapped module resolution.
|
||||
* Additionally, NGC expects types and imported packages to be within the project's root dir.
|
||||
*/
|
||||
function symlinkNodeModules() {
|
||||
Object.keys(requiredNodeModules).forEach(importName => {
|
||||
const outputPath = path.join(tmpDir, 'node_modules', importName);
|
||||
const moduleDir = requiredNodeModules[importName];
|
||||
|
||||
findFilesWithinDirectory(moduleDir).forEach(filePath => {
|
||||
const outputFilePath = path.join(outputPath, path.relative(moduleDir, filePath));
|
||||
|
||||
shx.mkdir('-p', path.dirname(outputFilePath));
|
||||
fs.symlinkSync(filePath, outputFilePath);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all source files for the integration test to a temporary directory. This
|
||||
* is necessary because runfiles resolve on Windows to the original source location,
|
||||
* and we don't want to pollute the workspace sources. This breaks hermeticity.
|
||||
*/
|
||||
function copySourceFilesToTempDir() {
|
||||
getSourceFilesFromRunfiles().forEach(({realPath, relativeFilePath}) => {
|
||||
const tmpFilePath = path.join(tmpDir, relativeFilePath);
|
||||
|
||||
shx.mkdir('-p', path.dirname(tmpFilePath));
|
||||
shx.cp(realPath, tmpFilePath);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all source files for the integration test by querying the Bazel runfiles.
|
||||
* In case there is a runfiles manifest (e.g. on Windows), the source files are resolved
|
||||
* through the manifest because on these platforms the runfiles are not symlinked and
|
||||
* cannot be searched within the real filesystem.
|
||||
*/
|
||||
function getSourceFilesFromRunfiles() {
|
||||
// Path to the Bazel runfiles manifest if present. This file is present if runfiles are
|
||||
// not symlinked into the runfiles directory.
|
||||
const runfilesManifestPath = process.env.RUNFILES_MANIFEST_FILE;
|
||||
|
||||
if (!runfilesManifestPath) {
|
||||
const packageRunfilesDir = path.join(process.env.RUNFILES, baseManifestPath);
|
||||
return findFilesWithinDirectory(packageRunfilesDir).map(filePath => ({
|
||||
realPath: filePath,
|
||||
relativeFilePath: path.relative(
|
||||
packageRunfilesDir, filePath)
|
||||
}));
|
||||
}
|
||||
|
||||
return fs.readFileSync(runfilesManifestPath, 'utf8')
|
||||
.split('\n')
|
||||
.map(mapping => mapping.split(' '))
|
||||
.filter(([runfilePath]) => runfilePath.startsWith(baseManifestPath))
|
||||
.map(
|
||||
([runfilePath, realPath]) =>
|
||||
({realPath, relativeFilePath: path.relative(baseManifestPath, runfilePath)}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a NPM package from the Bazel runfiles. We need to resolve the Bazel tree
|
||||
* artifacts using a "resolve file" because the NodeJS module resolution does not allow
|
||||
* resolving to directory paths.
|
||||
*/
|
||||
function resolveNpmTreeArtifact(manifestPath, resolveFile = 'package.json') {
|
||||
return path.dirname(require.resolve(path.posix.join(manifestPath, resolveFile)));
|
||||
}
|
||||
|
||||
/** Finds all files within a specified directory. */
|
||||
function findFilesWithinDirectory(directoryPath) {
|
||||
return shx.find(directoryPath).filter(filePath => !fs.statSync(filePath).isDirectory());
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"skipTemplateCodegen": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "../node_modules/third_party",
|
||||
// Prevent scanning up the directory tree for types
|
||||
"typeRoots": ["node_modules/@types"]
|
||||
"rootDir": "",
|
||||
"target": "es5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,34 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"alwaysCompileGeneratedCode": true,
|
||||
"annotationsAs": "static fields",
|
||||
"debug": true,
|
||||
"enableSummariesForJit": true,
|
||||
"alwaysCompileGeneratedCode": true,
|
||||
"i18nFormat": "xlf"
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": ".",
|
||||
// Prevent scanning up the directory tree for types
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"noUnusedLocals": true,
|
||||
"sourceMap": true
|
||||
"rootDir": "",
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strictNullChecks": true,
|
||||
// compatible with the option. Disabled until the integration test support the strict flag.
|
||||
// TODO(devversion): this has been enabled without the integration test code being
|
||||
"strictPropertyInitialization": false,
|
||||
"target": "es5"
|
||||
},
|
||||
|
||||
"files": [
|
||||
"src/module",
|
||||
"src/bootstrap",
|
||||
"test/all_spec",
|
||||
"test/test_ngtools_api",
|
||||
"benchmarks/src/tree/ng2/index_aot.ts",
|
||||
"benchmarks/src/tree/ng2_switch/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
|
||||
"test/test_ngtools_api"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"debug": true,
|
||||
"enableSummariesForJit": true,
|
||||
"alwaysCompileGeneratedCode": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true,
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": ".",
|
||||
// Prevent scanning up the directory tree for types
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"noUnusedLocals": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
|
||||
"files": [
|
||||
"src/module",
|
||||
"src/bootstrap",
|
||||
"test/all_spec",
|
||||
"test/test_ngtools_api",
|
||||
"benchmarks/src/tree/ng2/index_aot.ts",
|
||||
"benchmarks/src/tree/ng2_switch/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
|
||||
]
|
||||
}
|
||||
@@ -1,34 +1,26 @@
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"debug": true,
|
||||
"enableSummariesForJit": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./out",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": ".",
|
||||
// Prevent scanning up the directory tree for types
|
||||
"typeRoots": ["node_modules/@types"]
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "./xi18n-out",
|
||||
"rootDir": "",
|
||||
"skipLibCheck": true,
|
||||
"target": "es5"
|
||||
},
|
||||
|
||||
"files": [
|
||||
"src/module",
|
||||
"src/bootstrap",
|
||||
"test/all_spec",
|
||||
"test/test_ngtools_api",
|
||||
"benchmarks/src/tree/ng2/index_aot.ts",
|
||||
"benchmarks/src/tree/ng2_switch/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
|
||||
"test/test_ngtools_api"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
target: 'node',
|
||||
entry: './test/all_spec.js',
|
||||
output: {filename: './all_spec.js'},
|
||||
resolve: {extensions: ['.js']},
|
||||
devtool: '#source-map',
|
||||
module: {
|
||||
loaders:
|
||||
[{test: /\.js$/, exclude: /node_modules/, loaders: ['source-map-loader'], enforce: 'pre'}]
|
||||
},
|
||||
};
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"*.ts",
|
||||
"**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngcc",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
|
||||
@@ -23,7 +23,7 @@ yarn bazel test //packages/compiler-cli/src/ngcc/test
|
||||
|
||||
## Integration Testing
|
||||
|
||||
There are tests that check the behaviour of the overall executable:
|
||||
There are tests that check the behavior of the overall executable:
|
||||
|
||||
```bash
|
||||
yarn bazel test //packages/compiler-cli/test/ngcc
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/annotations",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/diagnostics",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"@ngdeps//typescript",
|
||||
|
||||
@@ -8,6 +8,5 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/host",
|
||||
deps = ["@ngdeps//typescript"],
|
||||
)
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/metadata",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/shims",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/host",
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/switch",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/host",
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/transform",
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
|
||||
@@ -5,7 +5,6 @@ load("//tools:defaults.bzl", "ts_library")
|
||||
ts_library(
|
||||
name = "translator",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/translator",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
|
||||
@@ -5,7 +5,6 @@ load("//tools:defaults.bzl", "ts_library")
|
||||
ts_library(
|
||||
name = "typecheck",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/typecheck",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
|
||||
@@ -8,7 +8,6 @@ ts_library(
|
||||
"index.ts",
|
||||
"src/**/*.ts",
|
||||
]),
|
||||
module_name = "@angular/compiler-cli/src/ngtsc/util",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"@ngdeps//@types/node",
|
||||
|
||||
@@ -10,7 +10,6 @@ ts_library(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/compiler",
|
||||
)
|
||||
|
||||
ng_package(
|
||||
@@ -27,6 +26,7 @@ ng_package(
|
||||
# Do not add more to this list.
|
||||
# Dependencies on the full npm_package cause long re-builds.
|
||||
visibility = [
|
||||
"//packages/compiler-cli/integrationtest:__pkg__",
|
||||
"//packages/language-service/test:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
|
||||
@@ -10,7 +10,6 @@ ng_module(
|
||||
["**/*.ts"],
|
||||
exclude = ["testing.ts"],
|
||||
),
|
||||
module_name = "@angular/compiler/testing",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
|
||||
@@ -10,7 +10,6 @@ ng_module(
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/core",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"@ngdeps//zone.js",
|
||||
@@ -33,6 +32,7 @@ ng_package(
|
||||
# Dependencies on the full npm_package cause long re-builds.
|
||||
visibility = [
|
||||
"//packages/bazel/test/ng_package:__pkg__",
|
||||
"//packages/compiler-cli/integrationtest:__pkg__",
|
||||
"//packages/compiler-cli/test:__pkg__",
|
||||
"//packages/compiler-cli/test/diagnostics:__pkg__",
|
||||
"//packages/compiler-cli/test/ngcc:__pkg__",
|
||||
|
||||
@@ -47,9 +47,11 @@ export abstract class TemplateRef<C> {
|
||||
abstract get elementRef(): ElementRef;
|
||||
|
||||
/**
|
||||
* Creates a view object and attaches it to the view container of the parent view.
|
||||
* @param context The context for the new view, inherited from the anchor element.
|
||||
* @returns The new view object.
|
||||
* Instantiates an embedded view based on this template,
|
||||
* and attaches it to the view container.
|
||||
* @param context The data-binding context of the embedded view, as declared
|
||||
* in the `<ng-template>` usage.
|
||||
* @returns The new embedded view object.
|
||||
*/
|
||||
abstract createEmbeddedView(context: C): EmbeddedViewRef<C>;
|
||||
|
||||
|
||||
@@ -240,8 +240,6 @@ export interface ContentChildDecorator {
|
||||
/**
|
||||
* Type of the ContentChild metadata.
|
||||
*
|
||||
* @see `ContentChild`.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export type ContentChild = Query;
|
||||
|
||||
@@ -482,8 +482,8 @@ export interface Component extends Directive {
|
||||
moduleId?: string;
|
||||
|
||||
/**
|
||||
* The URL of a template file for an Angular component. If provided,
|
||||
* do not supply an inline template using `template`.
|
||||
* The relative path or absolute URL of a template file for an Angular component.
|
||||
* If provided, do not supply an inline template using `template`.
|
||||
*
|
||||
*/
|
||||
templateUrl?: string;
|
||||
@@ -496,7 +496,7 @@ export interface Component extends Directive {
|
||||
template?: string;
|
||||
|
||||
/**
|
||||
* One or more URLs for files containing CSS stylesheets to use
|
||||
* One or more relative paths or absolute URLs for files containing CSS stylesheets to use
|
||||
* in this component.
|
||||
*/
|
||||
styleUrls?: string[];
|
||||
|
||||
@@ -1114,7 +1114,7 @@ describe('content projection', () => {
|
||||
* being re-assigned from one parent to another. Proposal: have compiler
|
||||
* to remove all but the latest occurrence of <ng-content> so we generate
|
||||
* only one P(n, m, 0) instruction. It would make it consistent with the
|
||||
* current Angular behaviour:
|
||||
* current Angular behavior:
|
||||
* http://plnkr.co/edit/OAYkNawTDPkYBFTqovTP?p=preview
|
||||
*/
|
||||
it('should project nodes into the last available ng-content', () => {
|
||||
|
||||
@@ -553,13 +553,13 @@ describe('query', () => {
|
||||
});
|
||||
|
||||
/**
|
||||
* BREAKING CHANGE: this tests asserts different behaviour as compared to Renderer2 when it
|
||||
* BREAKING CHANGE: this tests asserts different behavior as compared to Renderer2 when it
|
||||
* comes to descendants: false option and <ng-container>.
|
||||
*
|
||||
* Previous behaviour: queries with descendants: false would descend into <ng-container>.
|
||||
* New behaviour: queries with descendants: false would NOT descend into <ng-container>.
|
||||
* Previous behavior: queries with descendants: false would descend into <ng-container>.
|
||||
* New behavior: queries with descendants: false would NOT descend into <ng-container>.
|
||||
*
|
||||
* Reasoning: the Renderer2 behaviour is inconsistent and hard to explain to users when it
|
||||
* Reasoning: the Renderer2 behavior is inconsistent and hard to explain to users when it
|
||||
* comes to descendants: false interpretation (see
|
||||
* https://github.com/angular/angular/issues/14769#issuecomment-356609267) so we are changing
|
||||
* it in ngIvy.
|
||||
|
||||
@@ -9,7 +9,6 @@ ng_module(
|
||||
srcs = glob(
|
||||
["**/*.ts"],
|
||||
),
|
||||
module_name = "@angular/core/testing",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/core",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user