Compare commits
1 Commits
api-overlo
...
6.1.0-rc.0
Author | SHA1 | Date | |
---|---|---|---|
5bd3916608 |
@ -12,8 +12,8 @@
|
||||
## IMPORTANT
|
||||
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
|
||||
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
|
||||
var_1: &docker_image angular/ngcontainer:0.3.3
|
||||
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.3.3
|
||||
var_1: &docker_image angular/ngcontainer:0.3.2
|
||||
var_2: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.3.2
|
||||
|
||||
# Define common ENV vars
|
||||
var_3: &define_env_vars
|
||||
|
@ -22,7 +22,6 @@ node_modules_filegroup(
|
||||
"jasmine",
|
||||
"minimist",
|
||||
"protobufjs",
|
||||
"protractor",
|
||||
"reflect-metadata",
|
||||
"source-map-support",
|
||||
"tsickle",
|
||||
@ -35,9 +34,6 @@ node_modules_filegroup(
|
||||
"@types",
|
||||
"@webcomponents/custom-elements",
|
||||
],
|
||||
patterns = [
|
||||
"node_modules/protractor/**",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
@ -1,12 +1,3 @@
|
||||
<a name="6.0.9"></a>
|
||||
## [6.0.9](https://github.com/angular/angular/compare/6.0.8...6.0.9) (2018-07-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([3c93d07](https://github.com/angular/angular/commit/3c93d07)), closes [#24831](https://github.com/angular/angular/issues/24831)
|
||||
|
||||
|
||||
|
||||
<a name="6.1.0-rc.0"></a>
|
||||
# [6.1.0-rc.0](https://github.com/angular/angular/compare/6.1.0-beta.3...6.1.0-rc.0) (2018-07-11)
|
||||
|
||||
|
16
WORKSPACE
16
WORKSPACE
@ -13,16 +13,16 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_webtesting",
|
||||
url = "https://github.com/bazelbuild/rules_webtesting/archive/7ffe970bbf380891754487f66c3d680c087d67f2.zip",
|
||||
strip_prefix = "rules_webtesting-7ffe970bbf380891754487f66c3d680c087d67f2",
|
||||
sha256 = "4fb0dca8c9a90547891b7ef486592775a523330fc4555c88cd8f09270055c2ce",
|
||||
url = "https://github.com/bazelbuild/rules_webtesting/archive/v0.2.0.zip",
|
||||
strip_prefix = "rules_webtesting-0.2.0",
|
||||
sha256 = "cecc12f07e95740750a40d38e8b14b76fefa1551bef9332cb432d564d693723c",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_typescript",
|
||||
url = "https://github.com/bazelbuild/rules_typescript/archive/0.15.1.zip",
|
||||
strip_prefix = "rules_typescript-0.15.1",
|
||||
sha256 = "3792cc20ef13bb1d1d8b1760894c3320f02a87843e3a04fed7e8e454a75328b6",
|
||||
url = "https://github.com/rkirov/rules_typescript/archive/v0.16.0.zip",
|
||||
strip_prefix = "rules_typescript-0.16.0",
|
||||
sha256 = "f5aedd3a792e5af19cd0c0f0318cb692e2989e816e896e794152d07808fccacd",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@ -58,7 +58,7 @@ http_archive(
|
||||
# Even better, things like aspects will visit the entire graph including
|
||||
# ts_library rules in the devkit repository.
|
||||
http_archive(
|
||||
name = "angular_cli",
|
||||
name = "angular_devkit",
|
||||
url = "https://github.com/angular/angular-cli/archive/v6.1.0-rc.0.zip",
|
||||
strip_prefix = "angular-cli-6.1.0-rc.0",
|
||||
sha256 = "8cf320ea58c321e103f39087376feea502f20eaf79c61a4fdb05c7286c8684fd",
|
||||
@ -77,7 +77,7 @@ http_archive(
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
||||
|
||||
check_bazel_version("0.15.0")
|
||||
check_bazel_version("0.14.0")
|
||||
node_repositories(package_json = ["//:package.json"])
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
@ -40,7 +40,7 @@ Angular inserts an instance of the `HeroListComponent` view between those tags.
|
||||
|
||||
* `templateUrl`: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's _host view_.
|
||||
|
||||
* `providers`: An array of **dependency injection providers** for services that the component requires. In the example, this tells Angular how to provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display.
|
||||
* `providers`: An array of **dependency injection providers** for services that the component requires. In the example, this tells Angular how provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display.
|
||||
|
||||
<hr/>
|
||||
|
||||
@ -177,4 +177,4 @@ or modify aspects of DOM elements and components
|
||||
|
||||
You can also write your own directives. Components such as `HeroListComponent` are one kind of custom directive. You can also create custom structural and attribute directives.
|
||||
|
||||
<!-- PENDING: link to where to learn more about other kinds! -->
|
||||
<!-- PENDING: link to where to learn more about other kinds! -->
|
@ -216,9 +216,10 @@ You can also write `<link>` tags into the component's HTML template.
|
||||
|
||||
<div class="alert is-critical">
|
||||
|
||||
When building with the CLI, be sure to include the linked style file among the assets to be copied to the server as described in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-asset-configuration).
|
||||
The link tag's `href` URL must be relative to the
|
||||
_**application root**_, not relative to the component file.
|
||||
|
||||
Once included, the CLI will include the stylesheet, whether the link tag's href URL is relative to the application root or the component file.
|
||||
When building with the CLI, be sure to include the linked style file among the assets to be copied to the server as described in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-asset-configuration).
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -69,7 +69,7 @@ DOM event object in the `$event` variable which this code passes as a parameter
|
||||
|
||||
|
||||
The properties of an `$event` object vary depending on the type of DOM event. For example,
|
||||
a mouse event includes different information than an input box editing event.
|
||||
a mouse event includes different information than a input box editing event.
|
||||
|
||||
All [standard DOM event objects](https://developer.mozilla.org/en-US/docs/Web/API/Event)
|
||||
have a `target` property, a reference to the element that raised the event.
|
||||
|
@ -641,12 +641,6 @@
|
||||
"title": "Angular Academy (Canada)",
|
||||
"url": "http://www.angularacademy.ca"
|
||||
},
|
||||
"at": {
|
||||
"desc": "Angular Training teaches Angular on-site all over the world. Also provides consulting and mentoring.",
|
||||
"rev": true,
|
||||
"title": "Angular Training",
|
||||
"url": "http://www.angulartraining.com"
|
||||
},
|
||||
"-KLIBo_lm-WrK1Sjtt-2": {
|
||||
"desc": "Basic and Advanced training across Europe in German",
|
||||
"rev": true,
|
||||
|
@ -21,10 +21,10 @@
|
||||
|
||||
<article class="api-list-container l-content-small docs-content">
|
||||
<div *ngFor="let section of filteredSections | async" >
|
||||
<h2 *ngIf="section.items"><a [href]="section.path">{{section.title}}</a></h2>
|
||||
<ul class="api-list" *ngIf="section.items?.length">
|
||||
<h2>{{section.title}}</h2>
|
||||
<ul class="api-list">
|
||||
<ng-container *ngFor="let item of section.items">
|
||||
<li class="api-item">
|
||||
<li *ngIf="item.show" class="api-item">
|
||||
<a [href]="item.path"><span class="symbol {{item.docType}}"></span> {{item.title}}</a>
|
||||
</li>
|
||||
</ng-container>
|
||||
|
@ -36,13 +36,18 @@ describe('ApiListComponent', () => {
|
||||
*/
|
||||
function expectFilteredResult(label: string, itemTest: (item: ApiItem) => boolean) {
|
||||
component.filteredSections.subscribe(filtered => {
|
||||
filtered = filtered.filter(section => section.items);
|
||||
let badItem: ApiItem|undefined;
|
||||
expect(filtered.length).toBeGreaterThan(0, 'expected something');
|
||||
expect(filtered.every(section => section.items!.every(itemTest))).toBe(true, label);
|
||||
expect(filtered.every(section => section.items.every(
|
||||
item => {
|
||||
const ok = item.show === itemTest(item);
|
||||
if (!ok) { badItem = item; }
|
||||
return ok;
|
||||
}
|
||||
))).toBe(true, `${label} fail: ${JSON.stringify(badItem, null, 2)}`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
describe('#filteredSections', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
@ -60,45 +65,34 @@ describe('ApiListComponent', () => {
|
||||
expectFilteredResult('query: class', item => /class/.test(item.name));
|
||||
});
|
||||
|
||||
it('items should be an array for every item in section when query matches section name', () => {
|
||||
it('item.show should be true for every item in section when query matches section name', () => {
|
||||
component.setQuery('core');
|
||||
component.filteredSections.subscribe(filtered => {
|
||||
filtered = filtered.filter(section => Array.isArray(section.items));
|
||||
expect(filtered.length).toBe(1, 'only one section');
|
||||
expect(filtered[0].name).toBe('core');
|
||||
expect(filtered[0].items).toEqual(sections.find(section => section.name === 'core')!.items);
|
||||
expect(filtered[0].items.every(item => !!item.show)).toBe(true, 'all core items shown');
|
||||
});
|
||||
});
|
||||
|
||||
describe('section.items', () => {
|
||||
it('should null if there are no matching items and the section itself does not match', () => {
|
||||
component.setQuery('core');
|
||||
component.filteredSections.subscribe(filtered => {
|
||||
const commonSection = filtered.find(section => section.name === 'common')!;
|
||||
expect(commonSection.items).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be visible if they have the selected stability status', () => {
|
||||
component.setStatus({value: 'stable', title: 'Stable'});
|
||||
expectFilteredResult('status: stable', item => item.stability === 'stable');
|
||||
});
|
||||
|
||||
it('should be visible if they have the selected security status', () => {
|
||||
component.setStatus({value: 'security-risk', title: 'Security Risk'});
|
||||
expectFilteredResult('status: security-risk', item => item.securityRisk);
|
||||
});
|
||||
|
||||
it('should be visible if they match the selected API type', () => {
|
||||
component.setType({value: 'class', title: 'Class'});
|
||||
expectFilteredResult('type: class', item => item.docType === 'class');
|
||||
});
|
||||
it('item.show should be true for items with selected status', () => {
|
||||
component.setStatus({value: 'stable', title: 'Stable'});
|
||||
expectFilteredResult('status: stable', item => item.stability === 'stable');
|
||||
});
|
||||
|
||||
it('should have no sections and no items visible when there is no match', () => {
|
||||
it('item.show should be true for items with "security-risk" status when selected', () => {
|
||||
component.setStatus({value: 'security-risk', title: 'Security Risk'});
|
||||
expectFilteredResult('status: security-risk', item => item.securityRisk);
|
||||
});
|
||||
|
||||
it('item.show should be true for items of selected type', () => {
|
||||
component.setType({value: 'class', title: 'Class'});
|
||||
expectFilteredResult('type: class', item => item.docType === 'class');
|
||||
});
|
||||
|
||||
it('should have no sections and no items when no match', () => {
|
||||
component.setQuery('fizbuzz');
|
||||
component.filteredSections.subscribe(filtered => {
|
||||
expect(filtered.some(section => !!section.items)).toBeFalsy();
|
||||
expect(filtered.length).toBe(0, 'expected no sections');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -114,11 +108,9 @@ describe('ApiListComponent', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
component.filteredSections.subscribe(filtered => {
|
||||
filtered = filtered.filter(s => s.items);
|
||||
console.log(filtered);
|
||||
expect(filtered.length).toBe(1, 'sections');
|
||||
expect(filtered[0].name).toBe(section, 'section name');
|
||||
const items = filtered[0].items!;
|
||||
const items = filtered[0].items.filter(i => i.show);
|
||||
expect(items.length).toBe(1, 'items');
|
||||
|
||||
const item = items[0];
|
||||
@ -226,7 +218,6 @@ const apiSections: ApiSection[] = [
|
||||
{
|
||||
"name": "common",
|
||||
"title": "common",
|
||||
"path": "api/common",
|
||||
"items": [
|
||||
{
|
||||
"name": "class_1",
|
||||
@ -265,7 +256,6 @@ const apiSections: ApiSection[] = [
|
||||
{
|
||||
"name": "core",
|
||||
"title": "core",
|
||||
"path": "api/core",
|
||||
"items": [
|
||||
{
|
||||
"name": "class_3",
|
||||
|
@ -49,8 +49,7 @@ export class ApiListComponent implements OnInit {
|
||||
{ value: 'function', title: 'Function' },
|
||||
{ value: 'interface', title: 'Interface' },
|
||||
{ value: 'pipe', title: 'Pipe'},
|
||||
{ value: 'type-alias', title: 'Type alias' },
|
||||
{ value: 'package', title: 'Package'}
|
||||
{ value: 'type-alias', title: 'Type Alias' }
|
||||
];
|
||||
|
||||
statuses: Option[] = [
|
||||
@ -72,8 +71,7 @@ export class ApiListComponent implements OnInit {
|
||||
this.apiService.sections,
|
||||
this.criteriaSubject,
|
||||
(sections, criteria) => {
|
||||
return sections
|
||||
.map(section => ({ ...section, items: this.filterSection(section, criteria) }));
|
||||
return sections.filter(section => this.filterSection(section, criteria));
|
||||
}
|
||||
);
|
||||
|
||||
@ -109,8 +107,13 @@ export class ApiListComponent implements OnInit {
|
||||
//////// Private //////////
|
||||
|
||||
private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) {
|
||||
const items = section.items!.filter(item => {
|
||||
return matchesType() && matchesStatus() && matchesQuery();
|
||||
let showSection = false;
|
||||
|
||||
section.items.forEach(item => {
|
||||
item.show = matchesType() && matchesStatus() && matchesQuery();
|
||||
|
||||
// show section if any of its items will be shown
|
||||
showSection = showSection || item.show;
|
||||
|
||||
function matchesQuery() {
|
||||
return !query ||
|
||||
@ -129,8 +132,8 @@ export class ApiListComponent implements OnInit {
|
||||
}
|
||||
});
|
||||
|
||||
// If there are no items we still return an empty array if the section name matches and the type is 'package'
|
||||
return items.length ? items : (type === 'package' && (!query || section.name.indexOf(query) !== -1)) ? [] : null;
|
||||
return showSection;
|
||||
|
||||
}
|
||||
|
||||
// Get initial search criteria from URL search params
|
||||
|
@ -50,7 +50,7 @@ describe('ApiService', () => {
|
||||
describe('#sections', () => {
|
||||
|
||||
it('first subscriber should fetch sections', done => {
|
||||
const data = [{name: 'a', title: 'A', path: '', items: []}, {name: 'b', title: 'B', path: '', items: []}];
|
||||
const data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
|
||||
|
||||
service.sections.subscribe(sections => {
|
||||
expect(sections).toEqual(data);
|
||||
@ -61,7 +61,7 @@ describe('ApiService', () => {
|
||||
});
|
||||
|
||||
it('second subscriber should get previous sections and NOT trigger refetch', done => {
|
||||
const data = [{name: 'a', title: 'A', path: '', items: []}, {name: 'b', title: 'B', path: '', items: []}];
|
||||
const data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
|
||||
let subscriptions = 0;
|
||||
|
||||
service.sections.subscribe(sections => {
|
||||
@ -91,7 +91,7 @@ describe('ApiService', () => {
|
||||
|
||||
let call = 0;
|
||||
|
||||
let data = [{name: 'a', title: 'A', path: '', items: []}, {name: 'b', title: 'B', path: '', items: []}];
|
||||
let data = [{name: 'a', title: 'A', items: []}, {name: 'b', title: 'B', items: []}];
|
||||
|
||||
service.sections.subscribe(sections => {
|
||||
// called twice during this test
|
||||
@ -103,7 +103,7 @@ describe('ApiService', () => {
|
||||
httpMock.expectOne({}).flush(data);
|
||||
|
||||
// refresh/refetch
|
||||
data = [{name: 'c', title: 'C', path: '', items: []}];
|
||||
data = [{name: 'c', title: 'C', items: []}];
|
||||
service.fetchSections();
|
||||
httpMock.expectOne({}).flush(data);
|
||||
|
||||
|
@ -14,13 +14,14 @@ export interface ApiItem {
|
||||
docType: string;
|
||||
stability: string;
|
||||
securityRisk: boolean;
|
||||
|
||||
show?: boolean;
|
||||
}
|
||||
|
||||
export interface ApiSection {
|
||||
path: string;
|
||||
name: string;
|
||||
title: string;
|
||||
items: ApiItem[]|null;
|
||||
items: ApiItem[];
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
|
@ -28,7 +28,7 @@ h2 {
|
||||
h3 {
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
margin: 24px 0px 12px;
|
||||
margin: 24px 0px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@ -55,10 +55,6 @@ h6 {
|
||||
}
|
||||
|
||||
h2, h3, h4, h5, h6 {
|
||||
a {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
margin: 8px 0;
|
||||
}
|
||||
@ -109,7 +105,7 @@ table {
|
||||
border-collapse: collapse;
|
||||
border-radius: 2px;
|
||||
border-spacing: 0;
|
||||
margin: 12px 0 32px;
|
||||
margin: 0 0 32px 0;
|
||||
}
|
||||
|
||||
table tbody th {
|
||||
|
@ -1,8 +1,8 @@
|
||||
.api-body {
|
||||
|
||||
max-width: 1200px;
|
||||
|
||||
table {
|
||||
margin: 12px 0 24px;
|
||||
|
||||
th {
|
||||
text-transform: none;
|
||||
@ -18,12 +18,6 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
tbody > tr > td tr td:first-child {
|
||||
@media screen and (max-width: 480px) {
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 16px 0;
|
||||
}
|
||||
@ -47,217 +41,5 @@
|
||||
.short-description {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.parameters-table {
|
||||
margin-top: 0;
|
||||
font-size: 14px;
|
||||
box-shadow: none;
|
||||
|
||||
tr {
|
||||
border: 0;
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 8px 8px 8px 0;
|
||||
border: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td:nth-child(1) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.class-overview {
|
||||
position: relative;
|
||||
|
||||
code-example {
|
||||
clear: left;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-action-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.method-table th {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.method-table, .option-table {
|
||||
th {
|
||||
|
||||
.action-icons {
|
||||
a {
|
||||
color: $mediumgray;
|
||||
|
||||
.material-icons:hover {
|
||||
background: none;
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 6px 0;
|
||||
font-weight: bold;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.api-heading {
|
||||
padding: 5px 0;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.short-description {
|
||||
margin: 6px 0 0 10px;
|
||||
}
|
||||
|
||||
.properties-table {
|
||||
font-size: 14px;
|
||||
|
||||
thead th {
|
||||
&:nth-child(1) {
|
||||
width: 20%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
details.overloads {
|
||||
box-shadow: none;
|
||||
|
||||
.icon-action-header a {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.detail-contents {
|
||||
padding: 0;
|
||||
border: 1px solid $lightgray;
|
||||
border-radius: 2px;
|
||||
box-shadow: none;
|
||||
|
||||
> *:not(hr) {
|
||||
margin: 16px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
summary {
|
||||
height: inherit;
|
||||
padding: 0 8px 8px;
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
&.is-full-width {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.from-constructor, .read-only-property {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
font-style: italic;
|
||||
background-color: $lightgray;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.github-links {
|
||||
.material-icons {
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
font-size: 20px;
|
||||
&:hover {
|
||||
background-color: $mist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.api-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
// ____________________________________________
|
||||
|
||||
/*
|
||||
* General styling to make detail/summary tags look a bit more material
|
||||
* To get the best out of it you should structure your usage like this:
|
||||
*
|
||||
* ```
|
||||
* <details>
|
||||
* <summary>Some title</summary>
|
||||
* <div class="details-content">
|
||||
* Some content
|
||||
* </div>
|
||||
* </details>
|
||||
*
|
||||
*/
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
padding: 16px 24px;
|
||||
color: $black;
|
||||
height: 16px;
|
||||
display: block; // Remove the built in details marker in FF
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display: none; // Remove the built in details marker in webkit
|
||||
}
|
||||
}
|
||||
|
||||
details {
|
||||
box-shadow: 0 1px 4px 0 rgba($black, 0.37);
|
||||
|
||||
.detail-contents {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
&[open] > i.material-icons {
|
||||
@include rotate(180deg); // Rotate the icon
|
||||
}
|
||||
}
|
||||
}
|
114
aio/src/styles/2-modules/_api-pages.scss
Normal file
114
aio/src/styles/2-modules/_api-pages.scss
Normal file
@ -0,0 +1,114 @@
|
||||
.github-links {
|
||||
float: right;
|
||||
.material-icons {
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
font-size: 20px;
|
||||
&:hover {
|
||||
background-color: $mist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.api-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.api-body {
|
||||
|
||||
.class-overview {
|
||||
position: relative;
|
||||
|
||||
code-example {
|
||||
clear: left;
|
||||
}
|
||||
}
|
||||
|
||||
.method-table, .option-table {
|
||||
th {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
h3 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.github-links {
|
||||
a {
|
||||
color: $mediumgray;
|
||||
.material-icons:hover {
|
||||
background: none;
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 6px 0;
|
||||
font-weight: bold;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.api-heading {
|
||||
padding: 5px 0;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.short-description {
|
||||
margin: 6px 0 0 10px;
|
||||
}
|
||||
|
||||
.properties-table {
|
||||
font-size: 14px;
|
||||
|
||||
thead th {
|
||||
&:nth-child(1) {
|
||||
width: 20%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.parameters-table {
|
||||
margin-top: 0;
|
||||
font-size: 14px;
|
||||
td:nth-child(1) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
details.overloads {
|
||||
margin-left: -8px;
|
||||
|
||||
summary {
|
||||
height: inherit;
|
||||
padding: 8px 12px;
|
||||
h4 {
|
||||
margin: 0;
|
||||
clear: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.from-constructor, .read-only-property {
|
||||
font-style: italic;
|
||||
color: $blue;
|
||||
}
|
||||
}
|
48
aio/src/styles/2-modules/_details.scss
Normal file
48
aio/src/styles/2-modules/_details.scss
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* General styling to make detail/summary tags look a bit more material
|
||||
* To get the best out of it you should structure your usage like this:
|
||||
*
|
||||
* ```
|
||||
* <details>
|
||||
* <summary>Some title</summary>
|
||||
* <div class="details-content">
|
||||
* Some content
|
||||
* </div>
|
||||
* </details>
|
||||
*
|
||||
*/
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
padding: 16px 24px;
|
||||
color: $black;
|
||||
height: 16px;
|
||||
display: block; // Remove the built in details marker in FF
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display: none; // Remove the built in details marker in webkit
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '\E5CE'; // See https://material.io/icons/#ic_expand_less
|
||||
font-family: 'Material Icons';
|
||||
font-size: 24px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
@include rotate(0deg); // We will rotate 180 degrees when details is open
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
details {
|
||||
box-shadow: 0 1px 4px 0 rgba($black, 0.37);
|
||||
|
||||
.detail-contents {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
&[open] > summary::before {
|
||||
@include rotate(180deg); // Rotate the icon
|
||||
}
|
||||
}
|
@ -3,3 +3,12 @@ hr {
|
||||
background: $lightgray;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.hr-margin {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
padding: 0;
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
============================== */
|
||||
|
||||
@import 'alert';
|
||||
@import 'api-pages';
|
||||
@import 'api-list';
|
||||
@import 'buttons';
|
||||
@import 'callout';
|
||||
@ -10,6 +11,7 @@
|
||||
@import 'code';
|
||||
@import 'contribute';
|
||||
@import 'contributor';
|
||||
@import 'details';
|
||||
@import 'edit-page-cta';
|
||||
@import 'features';
|
||||
@import 'filetree';
|
||||
|
@ -105,7 +105,7 @@ $api-symbols: (
|
||||
content: 'T',
|
||||
background: $light-green-600
|
||||
),
|
||||
package: (
|
||||
module: (
|
||||
content: 'Pk',
|
||||
background: $purple-600
|
||||
)
|
||||
|
@ -33,7 +33,6 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||
.processor(require('./processors/simplifyMemberAnchors'))
|
||||
.processor(require('./processors/computeStability'))
|
||||
.processor(require('./processors/removeInjectableConstructors'))
|
||||
.processor(require('./processors/processPackages'))
|
||||
|
||||
/**
|
||||
* These are the API doc types that will be rendered to actual files.
|
||||
@ -41,7 +40,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||
* more Angular specific API types, such as decorators and directives.
|
||||
*/
|
||||
.factory(function API_DOC_TYPES_TO_RENDER(EXPORT_DOC_TYPES) {
|
||||
return EXPORT_DOC_TYPES.concat(['decorator', 'directive', 'pipe', 'package']);
|
||||
return EXPORT_DOC_TYPES.concat(['decorator', 'directive', 'pipe', 'module']);
|
||||
})
|
||||
|
||||
/**
|
||||
@ -59,10 +58,8 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||
return API_DOC_TYPES_TO_RENDER.concat(API_CONTAINED_DOC_TYPES);
|
||||
})
|
||||
|
||||
.factory(require('./readers/package-content'))
|
||||
|
||||
// Where do we get the source files?
|
||||
.config(function(readTypeScriptModules, readFilesProcessor, collectExamples, tsParser, packageContentFileReader) {
|
||||
.config(function(readTypeScriptModules, readFilesProcessor, collectExamples, tsParser) {
|
||||
|
||||
// Tell TypeScript how to load modules that start with with `@angular`
|
||||
tsParser.options.paths = { '@angular/*': [API_SOURCE_PATH + '/*'] };
|
||||
@ -105,19 +102,12 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||
'upgrade/static/index.ts',
|
||||
];
|
||||
|
||||
readFilesProcessor.fileReaders.push(packageContentFileReader);
|
||||
|
||||
// API Examples
|
||||
readFilesProcessor.sourceFiles = [
|
||||
{
|
||||
basePath: API_SOURCE_PATH,
|
||||
include: API_SOURCE_PATH + '/examples/**/*',
|
||||
fileReader: 'exampleFileReader'
|
||||
},
|
||||
{
|
||||
basePath: API_SOURCE_PATH,
|
||||
include: API_SOURCE_PATH + '/**/PACKAGE.md',
|
||||
fileReader: 'packageContentFileReader'
|
||||
}
|
||||
];
|
||||
collectExamples.exampleFolders.push('examples');
|
||||
@ -133,7 +123,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||
.config(function(computeStability, splitDescription, addNotYetDocumentedProperty, API_DOC_TYPES_TO_RENDER, API_DOC_TYPES) {
|
||||
computeStability.docTypes = API_DOC_TYPES_TO_RENDER;
|
||||
// Only split the description on the API docs
|
||||
splitDescription.docTypes = API_DOC_TYPES.concat(['package-content']);
|
||||
splitDescription.docTypes = API_DOC_TYPES;
|
||||
addNotYetDocumentedProperty.docTypes = API_DOC_TYPES;
|
||||
})
|
||||
|
||||
@ -190,7 +180,7 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
|
||||
generateApiListDoc.outputFolder = API_SEGMENT;
|
||||
|
||||
computePathsProcessor.pathTemplates.push({
|
||||
docTypes: ['package'],
|
||||
docTypes: ['module'],
|
||||
getPath: function computeModulePath(doc) {
|
||||
doc.moduleFolder = `${API_SEGMENT}/${doc.id.replace(/\/index$/, '')}`;
|
||||
return doc.moduleFolder;
|
||||
|
@ -33,7 +33,7 @@ describe('addSelectorsAsAliases processor', () => {
|
||||
{ docType: 'directive', name: 'NgModel', aliases: ['NgModel'], directiveOptions: { selector: '\'[ngModel]:not([formControlName]):not([formControl])\'' } },
|
||||
{ docType: 'component', name: 'MyComponent', aliases: ['MyComponent'], componentOptions: { selector: '\'my-component\'' } },
|
||||
{ docType: 'decorator', name: 'MyDecorator', aliases: ['MyDecorator'] },
|
||||
{ docType: 'package', name: 'myPackage', aliases: ['myPackage'], id: 'some/myPackage' },
|
||||
{ docType: 'module', name: 'myModule', aliases: ['myModule'], id: 'some/myModule' },
|
||||
{ docType: 'var', name: 'myVar', aliases: ['myVar'] },
|
||||
{ docType: 'let', name: 'myLet', aliases: ['myLet'] },
|
||||
{ docType: 'const', name: 'myConst', aliases: ['myConst'] },
|
||||
|
@ -14,14 +14,14 @@ describe('angular-api-package: computeApiBreadCrumbs processor', () => {
|
||||
});
|
||||
|
||||
it('should attach a breadCrumbs property to each of the API_DOC_TYPES_TO_RENDER docs', () => {
|
||||
const API_DOC_TYPES_TO_RENDER = ['class', 'interface', 'package'];
|
||||
const API_DOC_TYPES_TO_RENDER = ['class', 'interface', 'module'];
|
||||
const processor = processorFactory(API_DOC_TYPES_TO_RENDER);
|
||||
|
||||
const docs = [
|
||||
{ docType: 'class', name: 'ClassA', path: 'module-1/class-a', moduleDoc: { id: 'moduleOne', path: 'module-1' } },
|
||||
{ docType: 'interface', name: 'InterfaceB', path: 'module-2/interface-b', moduleDoc: { id: 'moduleTwo', path: 'module-2' } },
|
||||
{ docType: 'guide', name: 'Guide One', path: 'guide/guide-1' },
|
||||
{ docType: 'package', name: 'testing', id: 'http/testing', path: 'http/testing' },
|
||||
{ docType: 'module', name: 'testing', id: 'http/testing', path: 'http/testing' },
|
||||
];
|
||||
processor.$process(docs);
|
||||
|
||||
|
@ -8,7 +8,7 @@ module.exports = function computeSearchTitleProcessor() {
|
||||
case 'function':
|
||||
doc.searchTitle = `${doc.name}()`;
|
||||
break;
|
||||
case 'package':
|
||||
case 'module':
|
||||
doc.searchTitle = `${doc.id} package`;
|
||||
break;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ describe('computeSearchTitle processor', () => {
|
||||
{ docType: 'pipe', name: 'MyPipe', pipeOptions: { name: 'myPipe' } },
|
||||
{ docType: 'directive', name: 'MyDirective', directiveOptions: {} },
|
||||
{ docType: 'decorator', name: 'MyDecorator' },
|
||||
{ docType: 'package', name: 'myPackage', id: 'some/myPackage' },
|
||||
{ docType: 'module', name: 'myModule', id: 'some/myModule' },
|
||||
{ docType: 'var', name: 'myVar' },
|
||||
{ docType: 'let', name: 'myLet' },
|
||||
{ docType: 'const', name: 'myConst' },
|
||||
@ -45,7 +45,7 @@ describe('computeSearchTitle processor', () => {
|
||||
expect(docs[4].searchTitle).toBeUndefined();
|
||||
expect(docs[5].searchTitle).toBeUndefined();
|
||||
expect(docs[6].searchTitle).toBeUndefined();
|
||||
expect(docs[7].searchTitle).toEqual('some/myPackage package');
|
||||
expect(docs[7].searchTitle).toEqual('some/myModule package');
|
||||
expect(docs[8].searchTitle).toBeUndefined();
|
||||
expect(docs[9].searchTitle).toBeUndefined();
|
||||
expect(docs[10].searchTitle).toBeUndefined();
|
||||
|
@ -12,20 +12,19 @@ module.exports = function generateApiListDoc() {
|
||||
path: this.outputFolder + '/api-list.json',
|
||||
outputPath: this.outputFolder + '/api-list.json',
|
||||
data: docs
|
||||
.filter(doc => doc.docType === 'package')
|
||||
.map(getPackageInfo)
|
||||
.filter(doc => doc.docType === 'module')
|
||||
.map(getModuleInfo)
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function getPackageInfo(packageDoc) {
|
||||
const packageName = packageDoc.id.replace(/\/index$/, '');
|
||||
function getModuleInfo(moduleDoc) {
|
||||
const moduleName = moduleDoc.id.replace(/\/index$/, '');
|
||||
return {
|
||||
name: packageName.toLowerCase(),
|
||||
title: packageName,
|
||||
path: packageDoc.path,
|
||||
items: packageDoc.exports
|
||||
name: moduleName.toLowerCase(),
|
||||
title: moduleName,
|
||||
items: moduleDoc.exports
|
||||
// Ignore internals and private exports (indicated by the ɵ prefix)
|
||||
.filter(doc => !doc.internal && !doc.privateExport)
|
||||
.map(getExportInfo)
|
||||
|
@ -38,28 +38,28 @@ describe('generateApiListDoc processor', () => {
|
||||
it('should add an info object to the doc for each module doc', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [], path: 'common' },
|
||||
{ docType: 'package', id: '@angular/core/index', exports: [], path: 'core' },
|
||||
{ docType: 'package', id: '@angular/http/index', exports: [], path: 'http' },
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [] },
|
||||
{ docType: 'module', id: '@angular/core/index', exports: [] },
|
||||
{ docType: 'module', id: '@angular/http/index', exports: [] },
|
||||
];
|
||||
processor.$process(docs);
|
||||
expect(docs[3].data).toEqual([
|
||||
{ name: '@angular/common', title: '@angular/common', items: [], path: 'common' },
|
||||
{ name: '@angular/core', title: '@angular/core', items: [], path: 'core' },
|
||||
{ name: '@angular/http', title: '@angular/http', items: [], path: 'http' },
|
||||
{ name: '@angular/common', title: '@angular/common', items: [] },
|
||||
{ name: '@angular/core', title: '@angular/core', items: [] },
|
||||
{ name: '@angular/http', title: '@angular/http', items: [] },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should add info about each export on each module', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'directive', name: 'AaaAaa', path: 'aaa' },
|
||||
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' },
|
||||
{ docType: 'decorator', name: 'CccCcc', path: 'ccc' },
|
||||
{ docType: 'class', name: 'DddDdd', path: 'ddd' }
|
||||
] },
|
||||
{ docType: 'package', id: '@angular/core/index', exports: [
|
||||
{ docType: 'module', id: '@angular/core/index', exports: [
|
||||
{ docType: 'interface', name: 'EeeEee', path: 'eee' },
|
||||
{ docType: 'function', name: 'FffFff', path: 'fff' },
|
||||
{ docType: 'enum', name: 'GggGgg', path: 'ggg' },
|
||||
@ -86,7 +86,7 @@ describe('generateApiListDoc processor', () => {
|
||||
it('should ignore internal and private exports', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'directive', name: 'AaaAaa', path: 'aaa', internal: true },
|
||||
{ docType: 'class', name: 'XxxXxx', path: 'xxx', privateExport: true },
|
||||
{ docType: 'pipe', name: 'BbbBbb', path: 'bbb' }
|
||||
@ -101,7 +101,7 @@ describe('generateApiListDoc processor', () => {
|
||||
it('should convert `let` and `var` docTypes to `const`', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'var', name: 'AaaAaa', path: 'aaa' },
|
||||
{ docType: 'let', name: 'BbbBbb', path: 'bbb' },
|
||||
]}
|
||||
@ -116,7 +116,7 @@ describe('generateApiListDoc processor', () => {
|
||||
it('should convert security to a boolean securityRisk', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'class', name: 'AaaAaa', path: 'aaa', security: 'This is a security risk' },
|
||||
{ docType: 'class', name: 'BbbBbb', path: 'bbb', security: '' },
|
||||
]}
|
||||
@ -131,7 +131,7 @@ describe('generateApiListDoc processor', () => {
|
||||
it('should convert stability tags to the stable string property', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'class', name: 'AaaAaa', path: 'aaa', stable: undefined },
|
||||
{ docType: 'class', name: 'BbbBbb', path: 'bbb', experimental: 'Some message' },
|
||||
{ docType: 'class', name: 'CccCcc', path: 'ccc', deprecated: null },
|
||||
@ -150,7 +150,7 @@ describe('generateApiListDoc processor', () => {
|
||||
it('should sort items in each group alphabetically', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ docType: 'package', id: '@angular/common/index', exports: [
|
||||
{ docType: 'module', id: '@angular/common/index', exports: [
|
||||
{ docType: 'class', name: 'DddDdd', path: 'uuu' },
|
||||
{ docType: 'class', name: 'BbbBbb', path: 'vvv' },
|
||||
{ docType: 'class', name: 'AaaAaa', path: 'xxx' },
|
||||
|
@ -1,63 +0,0 @@
|
||||
const { dirname } = require('canonical-path');
|
||||
|
||||
module.exports = function processPackages() {
|
||||
return {
|
||||
$runAfter: ['extractDecoratedClassesProcessor'],
|
||||
$runBefore: ['computing-ids'],
|
||||
$process(docs) {
|
||||
const packageContentFiles = {};
|
||||
const packageMap = {};
|
||||
|
||||
docs = docs.filter(doc => {
|
||||
if (doc.docType === 'package-content') {
|
||||
packageContentFiles[dirname(doc.fileInfo.filePath)] = doc;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
docs.forEach(doc => {
|
||||
if (doc.docType === 'module') {
|
||||
// Convert the doc type from "module" to "package"
|
||||
doc.docType = 'package';
|
||||
// The name is actually the full id
|
||||
doc.name = `@angular/${doc.id}`;
|
||||
|
||||
// Partition the exports into groups by type
|
||||
if (doc.exports) {
|
||||
doc.classes = doc.exports.filter(doc => doc.docType === 'class');
|
||||
doc.decorators = doc.exports.filter(doc => doc.docType === 'decorator');
|
||||
doc.functions = doc.exports.filter(doc => doc.docType === 'function');
|
||||
doc.structures = doc.exports.filter(doc => doc.docType === 'enum' || doc.docType === 'interface');
|
||||
doc.directives = doc.exports.filter(doc => doc.docType === 'directive');
|
||||
doc.pipes = doc.exports.filter(doc => doc.docType === 'pipe');
|
||||
doc.types = doc.exports.filter(doc => doc.docType === 'type-alias' || doc.docType === 'const');
|
||||
}
|
||||
|
||||
// Copy over docs from the PACKAGE.md file that is used to document packages
|
||||
const readmeDoc = packageContentFiles[dirname(doc.fileInfo.filePath)];
|
||||
if (readmeDoc) {
|
||||
doc.shortDescription = readmeDoc.shortDescription;
|
||||
doc.description = readmeDoc.description;
|
||||
doc.see = readmeDoc.see;
|
||||
doc.fileInfo = readmeDoc.fileInfo;
|
||||
}
|
||||
|
||||
// Compute the primary/secondary entry point relationships
|
||||
const packageParts = doc.id.split('/');
|
||||
const primaryPackageName = packageParts[0];
|
||||
doc.isPrimaryPackage = packageParts.length === 1;
|
||||
doc.packageInfo = packageMap[primaryPackageName] = packageMap[primaryPackageName] || { primary: undefined, secondary: [] };
|
||||
if (doc.isPrimaryPackage) {
|
||||
doc.packageInfo.primary = doc;
|
||||
} else {
|
||||
doc.packageInfo.secondary.push(doc);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
@ -1,180 +0,0 @@
|
||||
const testPackage = require('../../helpers/test-package');
|
||||
const processorFactory = require('./processPackages');
|
||||
const Dgeni = require('dgeni');
|
||||
|
||||
describe('processPackages processor', () => {
|
||||
|
||||
it('should be available on the injector', () => {
|
||||
const dgeni = new Dgeni([testPackage('angular-api-package')]);
|
||||
const injector = dgeni.configureInjector();
|
||||
const processor = injector.get('processPackages');
|
||||
expect(processor.$process).toBeDefined();
|
||||
expect(processor.$runAfter).toEqual(['extractDecoratedClassesProcessor']);
|
||||
expect(processor.$runBefore).toEqual(['computing-ids']);
|
||||
});
|
||||
|
||||
it('should filter out any `package-content` docs from the collection', () => {
|
||||
const docs = [
|
||||
{ fileInfo: { filePath: 'some/a' }, docType: 'a', id: 'a' },
|
||||
{ fileInfo: { filePath: 'some/x' }, docType: 'package-content', id: 'x' },
|
||||
{ fileInfo: { filePath: 'some/b' }, docType: 'b', id: 'b' },
|
||||
{ fileInfo: { filePath: 'some/y' }, docType: 'package-content', id: 'y' },
|
||||
{ fileInfo: { filePath: 'some/z' }, docType: 'package-content', id: 'z' },
|
||||
];
|
||||
const processor = processorFactory();
|
||||
const newDocs = processor.$process(docs);
|
||||
expect(newDocs).toEqual([
|
||||
{ fileInfo: { filePath: 'some/a' }, docType: 'a', id: 'a' },
|
||||
{ fileInfo: { filePath: 'some/b' }, docType: 'b', id: 'b' },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
it('should change `module` docs to `package` docs', () => {
|
||||
const processor = processorFactory();
|
||||
const docs = [
|
||||
{ fileInfo: { filePath: 'some/a' }, docType: 'module', id: 'a' },
|
||||
{ fileInfo: { filePath: 'some/b' }, docType: 'module', id: 'b' },
|
||||
{ docType: 'other', id: 'c' },
|
||||
];
|
||||
const newDocs = processor.$process(docs);
|
||||
expect(newDocs).toEqual([
|
||||
jasmine.objectContaining({ docType: 'package', id: 'a' }),
|
||||
jasmine.objectContaining({ docType: 'package', id: 'b' }),
|
||||
jasmine.objectContaining({ docType: 'other', id: 'c' }),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should attach the relevant package contents to the package doc', () => {
|
||||
const docs = [
|
||||
{
|
||||
fileInfo: { filePath: 'some/package-1/index' },
|
||||
docType: 'module',
|
||||
id: 'package-1',
|
||||
someProp: 'foo',
|
||||
},
|
||||
{
|
||||
fileInfo: { filePath: 'some/package-1/PACKAGE.md' },
|
||||
docType: 'package-content',
|
||||
id: 'package-1/PACKAGE.md',
|
||||
shortDescription: 'some short description',
|
||||
description: 'some description',
|
||||
see: [ 'a', 'b' ],
|
||||
},
|
||||
{
|
||||
fileInfo: { filePath: 'some/package-2/index' },
|
||||
docType: 'module',
|
||||
id: 'package-2',
|
||||
},
|
||||
];
|
||||
const processor = processorFactory();
|
||||
const newDocs = processor.$process(docs);
|
||||
|
||||
const package1 = jasmine.objectContaining({
|
||||
fileInfo: { filePath: 'some/package-1/PACKAGE.md' },
|
||||
docType: 'package',
|
||||
name: '@angular/package-1',
|
||||
id: 'package-1',
|
||||
someProp: 'foo',
|
||||
shortDescription: 'some short description',
|
||||
description: 'some description',
|
||||
see: [ 'a', 'b' ],
|
||||
isPrimaryPackage: true,
|
||||
});
|
||||
|
||||
const package2 = jasmine.objectContaining({
|
||||
fileInfo: { filePath: 'some/package-2/index' },
|
||||
docType: 'package',
|
||||
name: '@angular/package-2',
|
||||
id: 'package-2',
|
||||
isPrimaryPackage: true,
|
||||
});
|
||||
|
||||
expect(newDocs).toEqual([package1, package2]);
|
||||
});
|
||||
|
||||
it('should compute primary and second package info', () => {
|
||||
const docs = [
|
||||
{
|
||||
fileInfo: { filePath: 'some/package-1/index' },
|
||||
docType: 'module',
|
||||
id: 'package-1',
|
||||
},
|
||||
{
|
||||
fileInfo: { filePath: 'some/package-1/sub-1index' },
|
||||
docType: 'module',
|
||||
id: 'package-1/sub-1',
|
||||
},
|
||||
{
|
||||
fileInfo: { filePath: 'some/package-1/sub-2index' },
|
||||
docType: 'module',
|
||||
id: 'package-1/sub-2',
|
||||
},
|
||||
];
|
||||
const processor = processorFactory();
|
||||
const newDocs = processor.$process(docs);
|
||||
|
||||
expect(newDocs[0].isPrimaryPackage).toBe(true);
|
||||
expect(newDocs[1].isPrimaryPackage).toBe(false);
|
||||
expect(newDocs[2].isPrimaryPackage).toBe(false);
|
||||
|
||||
expect(newDocs[0].packageInfo.primary).toBe(newDocs[0]);
|
||||
expect(newDocs[1].packageInfo.primary).toBe(newDocs[0]);
|
||||
expect(newDocs[2].packageInfo.primary).toBe(newDocs[0]);
|
||||
|
||||
expect(newDocs[0].packageInfo.secondary).toEqual([newDocs[1], newDocs[2]]);
|
||||
expect(newDocs[1].packageInfo.secondary).toEqual([newDocs[1], newDocs[2]]);
|
||||
expect(newDocs[2].packageInfo.secondary).toEqual([newDocs[1], newDocs[2]]);
|
||||
});
|
||||
|
||||
it('should partition the exports of packages into groups', () => {
|
||||
const docs = [
|
||||
{
|
||||
fileInfo: { filePath: 'some/x' },
|
||||
docType: 'module',
|
||||
id: 'x',
|
||||
exports: [
|
||||
{ docType: 'directive', id: 'directive-1' },
|
||||
{ docType: 'function', id: 'function-1' },
|
||||
{ docType: 'directive', id: 'directive-2' },
|
||||
{ docType: 'decorator', id: 'decorator-1' },
|
||||
{ docType: 'class', id: 'class-1' },
|
||||
{ docType: 'type-alias', id: 'type-alias-1' },
|
||||
{ docType: 'class', id: 'class-2' },
|
||||
{ docType: 'pipe', id: 'pipe-1' },
|
||||
{ docType: 'const', id: 'const-1' },
|
||||
{ docType: 'const', id: 'const-2' },
|
||||
{ docType: 'enum', id: 'enum-1' },
|
||||
{ docType: 'interface', id: 'interface-1' },
|
||||
{ docType: 'interface', id: 'interface-2' },
|
||||
]
|
||||
},
|
||||
];
|
||||
const processor = processorFactory();
|
||||
const newDocs = processor.$process(docs);
|
||||
|
||||
expect(newDocs[0].decorators).toEqual([
|
||||
{ docType: 'decorator', id: 'decorator-1' },
|
||||
]);
|
||||
expect(newDocs[0].functions).toEqual([
|
||||
{ docType: 'function', id: 'function-1' },
|
||||
]);
|
||||
expect(newDocs[0].structures).toEqual([
|
||||
{ docType: 'enum', id: 'enum-1' },
|
||||
{ docType: 'interface', id: 'interface-1' },
|
||||
{ docType: 'interface', id: 'interface-2' },
|
||||
]);
|
||||
expect(newDocs[0].directives).toEqual([
|
||||
{ docType: 'directive', id: 'directive-1' },
|
||||
{ docType: 'directive', id: 'directive-2' },
|
||||
]);
|
||||
expect(newDocs[0].pipes).toEqual([
|
||||
{ docType: 'pipe', id: 'pipe-1' },
|
||||
]);
|
||||
expect(newDocs[0].types).toEqual([
|
||||
{ docType: 'type-alias', id: 'type-alias-1' },
|
||||
{ docType: 'const', id: 'const-1' },
|
||||
{ docType: 'const', id: 'const-2' },
|
||||
]);
|
||||
});
|
||||
});
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @dgService
|
||||
* @description
|
||||
* This file reader will pull the contents from a text file that will be used
|
||||
* as the description of a package.
|
||||
*
|
||||
* The doc will initially have the form:
|
||||
* ```
|
||||
* {
|
||||
* content: 'the content of the file',
|
||||
* startingLine: 1
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
module.exports = function packageContentFileReader() {
|
||||
return {
|
||||
name: 'packageContentFileReader',
|
||||
defaultPattern: /PACKAGE\.md$/,
|
||||
getDocs: function(fileInfo) {
|
||||
|
||||
// We return a single element array because content files only contain one document
|
||||
return [{docType: 'package-content', content: fileInfo.content, startingLine: 1}];
|
||||
}
|
||||
};
|
||||
};
|
@ -14,7 +14,7 @@ module.exports = function createOverviewDump() {
|
||||
modules: []
|
||||
};
|
||||
_.forEach(docs, function(doc) {
|
||||
if (doc.docType === 'package') {
|
||||
if (doc.docType === 'module') {
|
||||
overviewDoc.modules.push(doc);
|
||||
}
|
||||
});
|
||||
|
@ -2,21 +2,19 @@
|
||||
{% set comma = joiner(',') %}
|
||||
{% set slash = joiner('/') %}
|
||||
<article>
|
||||
<div class="breadcrumb-container">
|
||||
<div class="breadcrumb">
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "http://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{%- for crumb in doc.breadCrumbs %}{$ comma() $}
|
||||
{ "@type": "ListItem", "position": {$ loop.index $}, "item": { "@id": "https://angular.io/{$ crumb.path $}", "name": "{$ crumb.text $}" } }{% endfor %}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
{% for crumb in doc.breadCrumbs %}{% if not loop.last %} {$ slash() $} {% if crumb.path %}<a href="{$ crumb.path $}">{$ crumb.text $}</a>{% else %}{$ crumb.text $}{% endif %}{% endif %}{% endfor %}
|
||||
</div>
|
||||
{$ github.githubLinks(doc, versionInfo) $}
|
||||
{$ github.githubLinks(doc, versionInfo) $}
|
||||
<div class="breadcrumb">
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "http://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{%- for crumb in doc.breadCrumbs %}{$ comma() $}
|
||||
{ "@type": "ListItem", "position": {$ loop.index $}, "item": { "@id": "https://angular.io/{$ crumb.path $}", "name": "{$ crumb.text $}" } }{% endfor %}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
{% for crumb in doc.breadCrumbs %}{% if not loop.last %} {$ slash() $} {% if crumb.path %}<a href="{$ crumb.path $}">{$ crumb.text $}</a>{% else %}{$ crumb.text $}{% endif %}{% endif %}{% endfor %}
|
||||
</div>
|
||||
<header class="api-header">
|
||||
<h1>{$ doc.name $}</h1>
|
||||
|
@ -1,12 +1,12 @@
|
||||
{% macro githubViewHref(doc, versionInfo) -%}
|
||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/packages/{$ doc.fileInfo.realProjectRelativePath or doc.fileInfo.relativePath $}#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/packages/{$ doc.fileInfo.realProjectRelativePath $}#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
||||
{% macro githubEditHref(doc, versionInfo) -%}
|
||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/edit/master/packages/{$ doc.fileInfo.realProjectRelativePath or doc.fileInfo.relativePath $}?message=docs(
|
||||
https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/edit/master/packages/{$ doc.fileInfo.realProjectRelativePath $}?message=docs(
|
||||
{%- if doc.moduleDoc %}{$ doc.moduleDoc.id.split('/')[0] $}
|
||||
{%- elseif doc.docType === 'package' %}{$ doc.id.split('/')[0] $}
|
||||
{%- elseif doc.docType === 'module' %}{$ doc.id.split('/')[0] $}
|
||||
{%- else %}...{%- endif -%}
|
||||
)%3A%20describe%20your%20change...#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}
|
||||
{%- endmacro -%}
|
||||
@ -16,4 +16,4 @@ https://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInf
|
||||
<a href="{$ githubEditHref(doc, versionInfo) $}" aria-label="Suggest Edits" title="Suggest Edits"><i class="material-icons" aria-hidden="true" role="img">mode_edit</i></a>
|
||||
<a href="{$ githubViewHref(doc, versionInfo) $}" aria-label="View Source" title="View Source"><i class="material-icons" aria-hidden="true" role="img">code</i></a>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
{%- endmacro -%}
|
@ -47,17 +47,17 @@
|
||||
|
||||
<code-example language="ts" hideCopy="true" linenums="false" class="no-box api-heading">{$ renderMemberSyntax(overload) $}</code-example>
|
||||
|
||||
<h6 class="no-anchor">Parameters</h6>
|
||||
<h4 class="no-anchor">Parameters</h4>
|
||||
{$ params.renderParameters(overload.parameterDocs, cssClass + '-parameters', cssClass + '-parameter') $}
|
||||
|
||||
{% if overload.type or overload.returns.type %}
|
||||
<h6 class="no-anchor">Returns</h6>
|
||||
<h4 class="no-anchor">Returns</h4>
|
||||
{% marked %}`{$ (overload.type or overload.returns.type) $}`{% if overload.returns %}: {$ overload.returns.description $}{% endif %}{% endmarked %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if overload.throws.length %}
|
||||
<h6 class="no-anchor">Throws</h6>
|
||||
<h4 class="no-anchor">Throws</h4>
|
||||
{% for error in overload.throws %}
|
||||
{% marked %}`{$ (error.typeList or 'Error') $}` {$ error.description $}{% endmarked %}
|
||||
{% endfor %}
|
||||
@ -73,7 +73,7 @@
|
||||
{%- macro renderMethodDetail(versionInfo, method, cssClass) -%}
|
||||
<a id="{$ method.anchor $}"></a>
|
||||
<table class="is-full-width method-table {$ cssClass $}">
|
||||
{% if method.name !== 'constructor' %}<thead><tr><th class="icon-action-header">
|
||||
{% if method.name !== 'constructor' %}<thead><tr><th>
|
||||
<h3>
|
||||
{% if method.isCallMember %}<i>call signature</i>
|
||||
{% elseif method.isNewMember %}<i>construct signature</i>
|
||||
@ -106,22 +106,12 @@
|
||||
<tr>
|
||||
<td>
|
||||
<details class="overloads">
|
||||
<summary>
|
||||
<div class="icon-action-header">
|
||||
<h4 class="no-anchor">Overloads</h4>
|
||||
<a>Show All <i class="material-icons">expand_more</i></a>
|
||||
</div>
|
||||
</summary>
|
||||
<summary><h4 class="no-anchor">{$ method.overloads.length $} overloads...</h4></summary>
|
||||
<div class="detail-contents">
|
||||
{% for overload in method.overloads %}
|
||||
<div>
|
||||
<h5 class="icon-action-header no-anchor">
|
||||
<span>Overload #_ of {$ method.overloads.length $}</span>
|
||||
<i class="material-icons">expand_more</i></h5>
|
||||
{% for overload in method.overloads %}
|
||||
{$ renderOverloadInfo(overload, cssClass + '-overload', method) $}
|
||||
{% if not loop.last %}<hr class="hr-margin">{% endif %}
|
||||
{% if not loop.last %}<hr class="hr-margin fullwidth">{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</td>
|
||||
@ -180,10 +170,10 @@
|
||||
<td><a id="{$ property.anchor $}"></a>{$ property.name $}</td>
|
||||
{% if hasTypes %}<td><label class="property-type-label"><code>{$ property.type | escape $}</code></label></td>{% endif %}
|
||||
<td>
|
||||
{%- if (property.isGetAccessor or property.isReadonly) and not property.isSetAccessor %}<span class='read-only-property'>Read Only</span>{% endif %}
|
||||
{%- if (property.isGetAccessor or property.isReadonly) and not property.isSetAccessor %}<span class='read-only-property'>Read-only.</span>{% endif %}
|
||||
{% if property.shortDescription %}{$ property.shortDescription | marked $}{% endif %}
|
||||
{$ (property.description or property.constructorParamDoc.description) | marked $}
|
||||
{% if property.constructorParamDoc %} <span class='from-constructor'>Declared in Constructor</span>{% endif %}
|
||||
{% if property.constructorParamDoc %} <span class='from-constructor'>Declared in constructor.</span>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
16
aio/tools/transforms/templates/api/module.template.html
Normal file
16
aio/tools/transforms/templates/api/module.template.html
Normal file
@ -0,0 +1,16 @@
|
||||
{% extends 'base.template.html' -%}
|
||||
|
||||
{% block body -%}
|
||||
|
||||
{% include "includes/deprecation.html" %}
|
||||
{% include "includes/description.html" %}
|
||||
|
||||
<section class="export-list">
|
||||
<ul>
|
||||
{% for export in doc.exports -%}
|
||||
<li><a href="{$ export.path $}">{$ export.name $}</a></li>
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{%- endblock %}
|
@ -1,40 +0,0 @@
|
||||
{% extends 'base.template.html' -%}
|
||||
|
||||
{% macro listItems(items, title) %}
|
||||
{% if items.length %}
|
||||
<section class="export-list">
|
||||
<h3>{$ title $}</h3>
|
||||
<table class="is-full-width list-table">
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td><code class="code-anchor">
|
||||
<a href="{$ item.path $}">{$ item.name $}</a></code></td>
|
||||
<td>{% if item.shortDescription %}{$ item.shortDescription | marked $}{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% block body -%}
|
||||
{% include "includes/deprecation.html" %}
|
||||
{$ doc.shortDescription | marked $}
|
||||
{% if doc.description %}{$ doc.description | marked $}{% endif %}
|
||||
|
||||
{% include "includes/see-also.html" %}
|
||||
|
||||
<h2>Entry points</h2>
|
||||
{$ listItems([doc.packageInfo.primary], 'Primary') $}
|
||||
{$ listItems(doc.packageInfo.secondary, 'Secondary') $}
|
||||
|
||||
|
||||
<h2>Exports</h2>
|
||||
{$ listItems(doc.classes, 'Classes') $}
|
||||
{$ listItems(doc.decorators, 'Decorators') $}
|
||||
{$ listItems(doc.functions, 'Functions') $}
|
||||
{$ listItems(doc.structures, 'Structures') $}
|
||||
{$ listItems(doc.directives, 'Directives') $}
|
||||
{$ listItems(doc.pipes, 'Pipes') $}
|
||||
{$ listItems(doc.types, 'Types') $}
|
||||
{%- endblock %}
|
@ -1,9 +1,5 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"protractor.conf.js",
|
||||
])
|
||||
|
||||
filegroup(
|
||||
name = "node_modules",
|
||||
srcs = glob(
|
||||
|
@ -13,9 +13,9 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_webtesting",
|
||||
url = "https://github.com/bazelbuild/rules_webtesting/archive/8fd9ce0fd9254bde251da0bc373d6cd08e811434.zip",
|
||||
strip_prefix = "rules_webtesting-8fd9ce0fd9254bde251da0bc373d6cd08e811434",
|
||||
sha256 = "4baee95fcfadfbaf868707af8accfd1cb98c5d13f808908e0152468bfb47f0f7",
|
||||
url = "https://github.com/bazelbuild/rules_webtesting/archive/v0.2.0.zip",
|
||||
strip_prefix = "rules_webtesting-0.2.0",
|
||||
sha256 = "cecc12f07e95740750a40d38e8b14b76fefa1551bef9332cb432d564d693723c",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@ -44,7 +44,7 @@ http_archive(
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||
|
||||
check_bazel_version("0.15.0")
|
||||
check_bazel_version("0.14.0")
|
||||
node_repositories(package_json = ["//:package.json"])
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
@ -18,13 +18,17 @@
|
||||
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
|
||||
"@types/jasmine": "2.8.7",
|
||||
"@types/source-map": "0.5.1",
|
||||
"concurrently": "3.5.1",
|
||||
"http-server": "0.11.1",
|
||||
"protractor": "file:../../node_modules/protractor",
|
||||
"tsutils": "file:../../node_modules/tsutils",
|
||||
"typescript": "file:../../node_modules/typescript"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "ngc -p angular.tsconfig.json",
|
||||
"test": "bazel build ... --noshow_progress && bazel test ..."
|
||||
"postinstall": "concurrently \"webdriver-manager update $CHROMEDRIVER_VERSION_ARG\" \"ngc -p angular.tsconfig.json\"",
|
||||
"test": "bazel build //... --noshow_progress && yarn e2e",
|
||||
"pree2e": "bazel build test/...",
|
||||
"e2e": "yarn e2e-prodserver && yarn e2e-devserver",
|
||||
"e2e-prodserver": "concurrently \"bazel run //src:prodserver\" \"while ! nc -z 127.0.0.1 5432; do sleep 1; done && protractor\" --kill-others --success first",
|
||||
"e2e-devserver": "concurrently \"bazel run //src:devserver\" \"while ! nc -z 127.0.0.1 5432; do sleep 1; done && protractor\" --kill-others --success first"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,9 @@
|
||||
exports.config = {
|
||||
specs: ['bazel-bin/test/e2e/*.spec.js'],
|
||||
capabilities: {browserName: 'chrome', chromeOptions: {args: ['--no-sandbox']}},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:5432/',
|
||||
framework: 'jasmine',
|
||||
getPageTimeout: 60 * 1000,
|
||||
allScriptsTimeout: 60 * 1000,
|
||||
};
|
||||
|
@ -1,5 +1,3 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
|
||||
# Allow targets under sub-packages to reference the tsconfig.json file
|
||||
@ -48,11 +46,15 @@ genrule(
|
||||
|
||||
nodejs_binary(
|
||||
name = "prodserver",
|
||||
args = [
|
||||
"./src",
|
||||
"-p",
|
||||
"5432",
|
||||
],
|
||||
data = [
|
||||
"index.html",
|
||||
":bundle",
|
||||
":zone.js",
|
||||
],
|
||||
entry_point = "http-server/bin/http-server",
|
||||
templated_args = ["src"],
|
||||
)
|
||||
|
@ -1,34 +1,7 @@
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
load("@angular//:index.bzl", "protractor_web_test_suite")
|
||||
|
||||
ts_library(
|
||||
name = "e2e",
|
||||
testonly = 1,
|
||||
srcs = ["app.spec.ts"],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "ts_on_prepare",
|
||||
testonly = 1,
|
||||
srcs = ["on-prepare.ts"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = ["@angular//src/protractor/utils"],
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "devserver_test",
|
||||
configuration = "//:protractor.conf.js",
|
||||
data = ["@angular//src/protractor/utils"],
|
||||
on_prepare = ":ts_on_prepare",
|
||||
server = "//src:devserver",
|
||||
deps = [":e2e"],
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "prodserver_test",
|
||||
configuration = "//:protractor.conf.js",
|
||||
data = ["@angular//src/protractor/utils"],
|
||||
on_prepare = ":ts_on_prepare",
|
||||
server = "//src:prodserver",
|
||||
deps = [":e2e"],
|
||||
srcs = glob(["*.ts"]),
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {browser, by, element} from 'protractor';
|
||||
import {browser, by, element, ExpectedConditions} from 'protractor';
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 120000;
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
import { browser } from 'protractor';
|
||||
import {OnPrepareConfig, runServer} from '@angular/bazel/protractor-utils';
|
||||
|
||||
export = function(config: OnPrepareConfig) {
|
||||
const portFlag = config.server.endsWith('prodserver') ? '-p' : '-port';
|
||||
return runServer(config.workspace, config.server, portFlag, [])
|
||||
.then(serverSpec => {
|
||||
const serverUrl = `http://localhost:${serverSpec.port}`;
|
||||
console.log(`Server has been started, starting tests against ${serverUrl}`);
|
||||
browser.baseUrl = serverUrl;
|
||||
});
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
}
|
@ -3,12 +3,12 @@
|
||||
|
||||
|
||||
"@angular/animations@file:../../dist/packages-dist/animations":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/bazel@file:../../dist/packages-dist/bazel":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
"@bazel/typescript" "^0.15.0"
|
||||
"@types/node" "6.0.84"
|
||||
@ -17,12 +17,12 @@
|
||||
shelljs "0.7.8"
|
||||
|
||||
"@angular/common@file:../../dist/packages-dist/common":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/compiler-cli@file:../../dist/packages-dist/compiler-cli":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
chokidar "^1.4.2"
|
||||
minimist "^1.2.0"
|
||||
@ -30,22 +30,22 @@
|
||||
tsickle "^0.29.0"
|
||||
|
||||
"@angular/compiler@file:../../dist/packages-dist/compiler":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/core@file:../../dist/packages-dist/core":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/platform-browser-dynamic@file:../../dist/packages-dist/platform-browser-dynamic":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/platform-browser@file:../../dist/packages-dist/platform-browser":
|
||||
version "6.1.0-beta.1"
|
||||
version "6.0.0-rc.5"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
@ -74,16 +74,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
|
||||
"@types/node@*":
|
||||
version "10.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.4.tgz#c74e8aec19e555df44609b8057311052a2c84d9e"
|
||||
version "10.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.1.4.tgz#606651d3f8a8bec08b8cb262161aab9209f4a29d"
|
||||
|
||||
"@types/node@6.0.84":
|
||||
version "6.0.84"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.84.tgz#193ffe5a9f42864d425ffd9739d95b753c6a1eab"
|
||||
|
||||
"@types/node@^6.0.46":
|
||||
version "6.0.113"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.113.tgz#4b41f38ad03e4b41f9dc259b3b58aecb22c9aebc"
|
||||
version "6.0.111"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.111.tgz#85f880a1bab78d395a5de9bcb5319e73a0c31400"
|
||||
|
||||
"@types/q@^0.0.32":
|
||||
version "0.0.32"
|
||||
@ -132,6 +132,10 @@ ajv@^5.1.0:
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.3.0"
|
||||
|
||||
ansi-regex@^0.2.0, ansi-regex@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
@ -140,6 +144,10 @@ ansi-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
|
||||
ansi-styles@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de"
|
||||
|
||||
ansi-styles@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
||||
@ -278,6 +286,16 @@ caseless@~0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||
|
||||
chalk@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174"
|
||||
dependencies:
|
||||
ansi-styles "^1.1.0"
|
||||
escape-string-regexp "^1.0.0"
|
||||
has-ansi "^0.1.0"
|
||||
strip-ansi "^0.3.0"
|
||||
supports-color "^0.2.0"
|
||||
|
||||
chalk@^1.1.1, chalk@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
||||
@ -337,10 +355,27 @@ combined-stream@1.0.6, combined-stream@~1.0.5:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
|
||||
concurrently@3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.5.1.tgz#ee8b60018bbe86b02df13e5249453c6ececd2521"
|
||||
dependencies:
|
||||
chalk "0.5.1"
|
||||
commander "2.6.0"
|
||||
date-fns "^1.23.0"
|
||||
lodash "^4.5.1"
|
||||
rx "2.3.24"
|
||||
spawn-command "^0.0.2-1"
|
||||
supports-color "^3.2.3"
|
||||
tree-kill "^1.1.0"
|
||||
|
||||
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
@ -359,6 +394,10 @@ dashdash@^1.12.0:
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
date-fns@^1.23.0:
|
||||
version "1.29.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6"
|
||||
|
||||
debug@2, debug@^2.1.2, debug@^2.2.0:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@ -418,7 +457,7 @@ ecstatic@^3.0.0:
|
||||
minimist "^1.1.0"
|
||||
url-join "^2.0.2"
|
||||
|
||||
escape-string-regexp@^1.0.2:
|
||||
escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
|
||||
@ -606,12 +645,22 @@ har-validator@~5.0.3:
|
||||
ajv "^5.1.0"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
has-ansi@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e"
|
||||
dependencies:
|
||||
ansi-regex "^0.2.0"
|
||||
|
||||
has-ansi@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
has-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
|
||||
|
||||
has-unicode@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
@ -845,6 +894,10 @@ lcid@^1.0.0:
|
||||
dependencies:
|
||||
invert-kv "^1.0.0"
|
||||
|
||||
lodash@^4.5.1:
|
||||
version "4.17.10"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
|
||||
|
||||
long@~3:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
|
||||
@ -1250,8 +1303,8 @@ requires-port@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
|
||||
resolve@^1.1.6:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
@ -1261,6 +1314,10 @@ rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1:
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
|
||||
rx@2.3.24:
|
||||
version "2.3.24"
|
||||
resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7"
|
||||
|
||||
"rxjs@file:../../node_modules/rxjs":
|
||||
version "6.0.0"
|
||||
dependencies:
|
||||
@ -1270,7 +1327,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0,
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2:
|
||||
"safer-buffer@>= 2.1.2 < 3":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
|
||||
@ -1356,15 +1413,18 @@ source-map@^0.6.0:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
|
||||
spawn-command@^0.0.2-1:
|
||||
version "0.0.2-1"
|
||||
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.14.2"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb"
|
||||
dependencies:
|
||||
asn1 "~0.2.3"
|
||||
assert-plus "^1.0.0"
|
||||
dashdash "^1.12.0"
|
||||
getpass "^0.1.1"
|
||||
safer-buffer "^2.0.2"
|
||||
optionalDependencies:
|
||||
bcrypt-pbkdf "^1.0.0"
|
||||
ecc-jsbn "~0.1.1"
|
||||
@ -1392,6 +1452,12 @@ string_decoder@~1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
strip-ansi@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220"
|
||||
dependencies:
|
||||
ansi-regex "^0.2.1"
|
||||
|
||||
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
@ -1408,10 +1474,20 @@ strip-json-comments@~2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
|
||||
supports-color@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
|
||||
|
||||
supports-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||
|
||||
supports-color@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
|
||||
dependencies:
|
||||
has-flag "^1.0.0"
|
||||
|
||||
tar@^4:
|
||||
version "4.4.4"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd"
|
||||
@ -1440,6 +1516,10 @@ tough-cookie@~2.3.3:
|
||||
dependencies:
|
||||
punycode "^1.4.1"
|
||||
|
||||
tree-kill@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36"
|
||||
|
||||
tsickle@^0.29.0:
|
||||
version "0.29.0"
|
||||
resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.29.0.tgz#812806554bb46c1aa16eb0fe2a051da95ca8f5a4"
|
||||
@ -1449,15 +1529,10 @@ tsickle@^0.29.0:
|
||||
source-map "^0.6.0"
|
||||
source-map-support "^0.5.0"
|
||||
|
||||
tslib@^1.8.1, tslib@^1.9.0:
|
||||
tslib@^1.9.0:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e"
|
||||
|
||||
"tsutils@file:../../node_modules/tsutils":
|
||||
version "2.20.0"
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||
@ -1469,7 +1544,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
|
||||
"typescript@file:../../node_modules/typescript":
|
||||
version "2.8.3"
|
||||
version "2.7.2"
|
||||
|
||||
ultron@1.0.x:
|
||||
version "1.0.2"
|
||||
|
@ -77,7 +77,7 @@ module.exports = function(config) {
|
||||
'dist/all/@angular/compiler/test/aot/**',
|
||||
'dist/all/@angular/compiler/test/render3/**',
|
||||
'dist/all/@angular/core/test/bundling/**',
|
||||
'dist/all/@angular/core/test/render3/ivy/**',
|
||||
'dist/all/@angular/core/test/render3/**',
|
||||
'dist/all/@angular/elements/schematics/**',
|
||||
'dist/all/@angular/examples/**/e2e_test/*',
|
||||
'dist/all/@angular/language-service/**',
|
||||
|
@ -48,13 +48,13 @@ export class LargeTableComponent {
|
||||
{
|
||||
if (rf2 & RenderFlags.Create) {
|
||||
E(0, 'td');
|
||||
s(c0);
|
||||
{ T(1); }
|
||||
s(1, c0);
|
||||
{ T(2); }
|
||||
e();
|
||||
}
|
||||
if (rf2 & RenderFlags.Update) {
|
||||
sp(0, 0, cell.row % 2 ? '' : 'grey');
|
||||
t(1, b(cell.value));
|
||||
sp(1, 0, cell.row % 2 ? '' : 'grey');
|
||||
t(2, b(cell.value));
|
||||
}
|
||||
}
|
||||
v();
|
||||
|
@ -41,16 +41,16 @@ export class TreeComponent {
|
||||
template: function(rf: RenderFlags, ctx: TreeComponent) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
E(0, 'span');
|
||||
s(c0);
|
||||
{ T(1); }
|
||||
s(1, c0);
|
||||
{ T(2); }
|
||||
e();
|
||||
C(2);
|
||||
C(3);
|
||||
C(4);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
sp(0, 0, ctx.data.depth % 2 ? '' : 'grey');
|
||||
t(1, i1(' ', ctx.data.value, ' '));
|
||||
cR(2);
|
||||
sp(1, 0, ctx.data.depth % 2 ? '' : 'grey');
|
||||
t(2, i1(' ', ctx.data.value, ' '));
|
||||
cR(3);
|
||||
{
|
||||
if (ctx.data.left != null) {
|
||||
let rf0 = V(0);
|
||||
@ -67,7 +67,7 @@ export class TreeComponent {
|
||||
}
|
||||
}
|
||||
cr();
|
||||
cR(3);
|
||||
cR(4);
|
||||
{
|
||||
if (ctx.data.right != null) {
|
||||
let rf0 = V(0);
|
||||
@ -114,18 +114,18 @@ export function TreeTpl(rf: RenderFlags, ctx: TreeNode) {
|
||||
E(0, 'tree');
|
||||
{
|
||||
E(1, 'span');
|
||||
s(c1);
|
||||
{ T(2); }
|
||||
s(2, c1);
|
||||
{ T(3); }
|
||||
e();
|
||||
C(3);
|
||||
C(4);
|
||||
C(5);
|
||||
}
|
||||
e();
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
sp(1, 0, ctx.depth % 2 ? '' : 'grey');
|
||||
t(2, i1(' ', ctx.value, ' '));
|
||||
cR(3);
|
||||
sp(2, 0, ctx.depth % 2 ? '' : 'grey');
|
||||
t(3, i1(' ', ctx.value, ' '));
|
||||
cR(4);
|
||||
{
|
||||
if (ctx.left != null) {
|
||||
let rf0 = V(0);
|
||||
@ -134,7 +134,7 @@ export function TreeTpl(rf: RenderFlags, ctx: TreeNode) {
|
||||
}
|
||||
}
|
||||
cr();
|
||||
cR(4);
|
||||
cR(5);
|
||||
{
|
||||
if (ctx.right != null) {
|
||||
let rf0 = V(0);
|
||||
|
@ -26,7 +26,6 @@ ng_package(
|
||||
entry_point = "packages/animations/index.js",
|
||||
tags = [
|
||||
"ivy-jit",
|
||||
"ivy-local",
|
||||
"release-with-framework",
|
||||
],
|
||||
deps = [
|
||||
|
@ -1,29 +0,0 @@
|
||||
Implements a domain-specific language (DSL) for defining web animation sequences for HTML elements as
|
||||
multiple transformations over time.
|
||||
|
||||
Use this API to define how an HTML element can move, change color, grow or shrink, fade, or slide off
|
||||
the page. These changes can occur simultaneously or sequentially. You can control the timing of each
|
||||
of these transformations. The function calls generate the data structures and metadata that enable Angular
|
||||
to integrate animations into templates and run them based on application states.
|
||||
|
||||
Animation definitions are linked to components through the `{@link Component.animations animations}`
|
||||
property in the `@Component` metadata, typically in the component file of the HTML element to be animated.
|
||||
The `trigger()` function encapsulates a named animation, with all other function calls nested within. Use
|
||||
the trigger name to bind the named animation to a specific triggering element in the HTML template.
|
||||
|
||||
Angular animations are based on CSS web transition functionality, so anything that can be styled or
|
||||
transformed in CSS can be animated the same way in Angular. Angular animations allow you to:
|
||||
|
||||
* Set animation timings, styles, keyframes, and transitions.
|
||||
* Animate HTML elements in complex sequences and choreographies.
|
||||
* Animate HTML elements as they are inserted and removed from the DOM, including responsive real-time
|
||||
filtering.
|
||||
* Create reusable animations.
|
||||
* Animate parent and child elements.
|
||||
|
||||
Additional animation functionality is provided in other Angular modules for animation testing, for
|
||||
route-based animations, and for programmatic animation controls that allow an end user to fast forward
|
||||
and reverse an animation sequence.
|
||||
|
||||
@see Find out more in the [animations guide](guide/animations).
|
||||
@see See what polyfills you might need in the [browser support guide](guide/browser-support).
|
@ -9,11 +9,6 @@ Users should not load files under "/src"
|
||||
|
||||
load("//packages/bazel/src:ng_module.bzl", _ng_module = "ng_module")
|
||||
load("//packages/bazel/src/ng_package:ng_package.bzl", _ng_package = "ng_package")
|
||||
load("//packages/bazel/src/protractor:protractor_web_test.bzl",
|
||||
_protractor_web_test = "protractor_web_test",
|
||||
_protractor_web_test_suite = "protractor_web_test_suite")
|
||||
|
||||
ng_module = _ng_module
|
||||
ng_package = _ng_package
|
||||
protractor_web_test = _protractor_web_test
|
||||
protractor_web_test_suite = _protractor_web_test_suite
|
||||
|
@ -5,7 +5,6 @@ filegroup(
|
||||
srcs = glob(["*"]) + [
|
||||
"//packages/bazel/src/ng_package:package_assets",
|
||||
"//packages/bazel/src/ngc-wrapped:package_assets",
|
||||
"//packages/bazel/src/protractor:package_assets",
|
||||
],
|
||||
visibility = ["//packages/bazel:__subpackages__"],
|
||||
)
|
||||
@ -14,7 +13,7 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||
|
||||
nodejs_binary(
|
||||
name = "rollup_with_build_optimizer",
|
||||
data = ["@angular_cli//packages/angular_devkit/build_optimizer:lib"],
|
||||
data = ["@angular_devkit//packages/angular_devkit/build_optimizer:lib"],
|
||||
# Since our rule extends the one in rules_nodejs, we use the same runtime
|
||||
# dependency @build_bazel_rules_nodejs_rollup_deps. We don't need any
|
||||
# additional npm dependencies when we run rollup or uglify.
|
||||
|
@ -24,7 +24,7 @@ load(":esm5.bzl", "esm5_outputs_aspect", "flatten_esm5", "esm5_root_dir")
|
||||
PACKAGES=["packages/core/src", "packages/common/src", "packages/compiler/src", "external/rxjs"]
|
||||
PLUGIN_CONFIG="{sideEffectFreeModules: [\n%s]}" % ",\n".join(
|
||||
[" '.esm5/{0}'".format(p) for p in PACKAGES])
|
||||
BO_ROLLUP="angular_cli/packages/angular_devkit/build_optimizer/src/build-optimizer/rollup-plugin.js"
|
||||
BO_ROLLUP="angular_devkit/packages/angular_devkit/build_optimizer/src/build-optimizer/rollup-plugin.js"
|
||||
BO_PLUGIN="require('%s').default(%s)" % (BO_ROLLUP, PLUGIN_CONFIG)
|
||||
|
||||
def _use_plain_rollup(ctx):
|
||||
|
@ -1,13 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "package_assets",
|
||||
srcs = glob(["*"]) + [
|
||||
"//packages/bazel/src/protractor/utils:package_assets",
|
||||
],
|
||||
visibility = ["//packages/bazel:__subpackages__"],
|
||||
)
|
||||
|
||||
exports_files([
|
||||
"protractor.conf.js",
|
||||
])
|
@ -1,154 +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
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const DEBUG = false;
|
||||
|
||||
const configPath = 'TMPL_config';
|
||||
const onPreparePath = 'TMPL_on_prepare';
|
||||
const workspace = 'TMPL_workspace';
|
||||
const server = 'TMPL_server';
|
||||
|
||||
if (DEBUG)
|
||||
console.info(`Protractor test starting with:
|
||||
cwd: ${process.cwd()}
|
||||
configPath: ${configPath}
|
||||
onPreparePath: ${onPreparePath}
|
||||
workspace: ${workspace}
|
||||
server: ${server}`);
|
||||
|
||||
// Helper function to warn when a user specified value is being overwritten
|
||||
function setConf(conf, name, value, msg) {
|
||||
if (conf[name] && conf[name] !== value) {
|
||||
console.warn(
|
||||
`Your protractor configuration specifies an option which is overwritten by Bazel: '${name}' ${msg}`);
|
||||
}
|
||||
conf[name] = value;
|
||||
}
|
||||
|
||||
let conf = {};
|
||||
|
||||
// Import the user's base protractor configuration if specified
|
||||
if (configPath) {
|
||||
const baseConf = require(configPath);
|
||||
if (!baseConf.config) {
|
||||
throw new Error('Invalid base protractor configration. Expected config to be exported.');
|
||||
}
|
||||
conf = baseConf.config;
|
||||
}
|
||||
|
||||
// Import the user's on prepare function if specified
|
||||
if (onPreparePath) {
|
||||
const onPrepare = require(onPreparePath);
|
||||
if (typeof onPrepare === 'function') {
|
||||
const original = conf.onPrepare;
|
||||
conf.onPrepare = function() {
|
||||
return Promise.resolve(original ? original() : null)
|
||||
.then(() => Promise.resolve(onPrepare({workspace, server})));
|
||||
};
|
||||
} else {
|
||||
throw new Error(
|
||||
'Invalid protractor on_prepare script. Expected a function as the default export.');
|
||||
}
|
||||
}
|
||||
|
||||
// Override the user's base protractor configuration as appropriate based on the
|
||||
// ts_web_test_suite & rules_webtesting WEB_TEST_METADATA attributes
|
||||
setConf(conf, 'framework', 'jasmine2', 'is set to jasmine2');
|
||||
|
||||
const specs = [TMPL_specs]
|
||||
.map(s => require.resolve(s))
|
||||
.filter(s => s.endsWith('.spec.js') || s.endsWith('.test.js'));
|
||||
|
||||
setConf(conf, 'specs', specs, 'are determined by the srcs and deps attribute');
|
||||
|
||||
// WEB_TEST_METADATA is configured in rules_webtesting based on value
|
||||
// of the browsers attribute passed to ts_web_test_suite
|
||||
// We setup the protractor configuration based on the values in this object
|
||||
if (process.env['WEB_TEST_METADATA']) {
|
||||
const webTestMetadata = require(process.env['WEB_TEST_METADATA']);
|
||||
if (DEBUG) console.info(`WEB_TEST_METADATA: ${JSON.stringify(webTestMetadata, null, 2)}`);
|
||||
if (webTestMetadata['environment'] === 'sauce') {
|
||||
// If a sauce labs browser is chosen for the test such as
|
||||
// "@io_bazel_rules_webtesting//browsers/sauce:chrome-win10"
|
||||
// than the 'environment' will equal 'sauce'.
|
||||
// We expect that a SAUCE_USERNAME and SAUCE_ACCESS_KEY is available
|
||||
// from the environment for this test to run
|
||||
|
||||
// TODO(gmagolan): implement sauce labs support for protractor
|
||||
throw new Error('Saucelabs not yet support by protractor_web_test_suite.');
|
||||
|
||||
// if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
|
||||
// console.error('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are
|
||||
// set.');
|
||||
// process.exit(1);
|
||||
// }
|
||||
// setConf(conf, 'sauceUser', process.env.SAUCE_USERNAME, 'is determined by the SAUCE_USERNAME
|
||||
// environment variable');
|
||||
// setConf(conf, 'sauceKey', process.env.SAUCE_ACCESS_KEY, 'is determined by the
|
||||
// SAUCE_ACCESS_KEY environment variable');
|
||||
} else if (webTestMetadata['environment'] === 'local') {
|
||||
// When a local chrome or firefox browser is chosen such as
|
||||
// "@io_bazel_rules_webtesting//browsers:chromium-local" or
|
||||
// "@io_bazel_rules_webtesting//browsers:firefox-local"
|
||||
// then the 'environment' will equal 'local' and
|
||||
// 'webTestFiles' will contain the path to the binary to use
|
||||
const webTestNamedFiles = webTestMetadata['webTestFiles'][0]['namedFiles'];
|
||||
const headless = !process.env['DISPLAY'];
|
||||
if (webTestNamedFiles['CHROMIUM']) {
|
||||
const chromeBin = path.join(process.cwd(), 'external', webTestNamedFiles['CHROMIUM']);
|
||||
const args = [];
|
||||
if (headless) {
|
||||
args.push('--headless');
|
||||
args.push('--disable-gpu');
|
||||
}
|
||||
setConf(conf, 'directConnect', true, 'is set to true for chrome');
|
||||
setConf(
|
||||
conf, 'chromeDriver',
|
||||
path.join(process.cwd(), 'external', webTestNamedFiles['CHROMEDRIVER']),
|
||||
'is determined by the browsers attribute');
|
||||
setConf(
|
||||
conf, 'capabilities', {
|
||||
browserName: 'chrome',
|
||||
chromeOptions: {
|
||||
binary: chromeBin,
|
||||
args: args,
|
||||
}
|
||||
},
|
||||
'is determined by the browsers attribute');
|
||||
}
|
||||
if (webTestNamedFiles['FIREFOX']) {
|
||||
// TODO(gmagolan): implement firefox support for protractor
|
||||
throw new Error('Firefox not yet support by protractor_web_test_suite');
|
||||
|
||||
// const firefoxBin = path.join('external', webTestNamedFiles['FIREFOX']);
|
||||
// const args = [];
|
||||
// if (headless) {
|
||||
// args.push("--headless")
|
||||
// args.push("--marionette")
|
||||
// }
|
||||
// setConf(conf, 'seleniumAddress', process.env.WEB_TEST_HTTP_SERVER.trim() + "/wd/hub", 'is
|
||||
// configured by Bazel for firefox browser')
|
||||
// setConf(conf, 'capabilities', {
|
||||
// browserName: "firefox",
|
||||
// 'moz:firefoxOptions': {
|
||||
// binary: firefoxBin,
|
||||
// args: args,
|
||||
// }
|
||||
// }, 'is determined by the browsers attribute');
|
||||
}
|
||||
} else {
|
||||
console.warn(`Unknown WEB_TEST_METADATA environment '${webTestMetadata['environment']}'`);
|
||||
}
|
||||
}
|
||||
|
||||
// Export the complete protractor configuration
|
||||
if (DEBUG) console.info(`Protractor configuration: ${JSON.stringify(conf, null, 2)}`);
|
||||
|
||||
exports.config = conf;
|
@ -1,341 +0,0 @@
|
||||
# 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
|
||||
"""Implementation of the protractor_web_test and protractor_web_test_suite rules.
|
||||
"""
|
||||
|
||||
load("@build_bazel_rules_nodejs//internal:node.bzl",
|
||||
"sources_aspect",
|
||||
"expand_path_into_runfiles",
|
||||
)
|
||||
load("@io_bazel_rules_webtesting//web:web.bzl", "web_test_suite")
|
||||
load("@io_bazel_rules_webtesting//web/internal:constants.bzl", "DEFAULT_WRAPPED_TEST_TAGS")
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||
|
||||
_CONF_TMPL = "//packages/bazel/src/protractor:protractor.conf.js"
|
||||
|
||||
def _protractor_web_test_impl(ctx):
|
||||
configuration = ctx.actions.declare_file(
|
||||
"%s.conf.js" % ctx.label.name,
|
||||
sibling=ctx.outputs.executable)
|
||||
|
||||
files = depset(ctx.files.srcs)
|
||||
for d in ctx.attr.deps:
|
||||
if hasattr(d, "node_sources"):
|
||||
files = depset(transitive = [files, d.node_sources])
|
||||
elif hasattr(d, "files"):
|
||||
files = depset(transitive = [files, d.files])
|
||||
|
||||
specs = [
|
||||
expand_path_into_runfiles(ctx, f.short_path)
|
||||
for f in files
|
||||
]
|
||||
|
||||
configuration_sources = []
|
||||
if ctx.file.configuration:
|
||||
configuration_sources = [ctx.file.configuration]
|
||||
if hasattr(ctx.attr.configuration, "node_sources"):
|
||||
configuration_sources = ctx.attr.configuration.node_sources.to_list()
|
||||
|
||||
configuration_file = ctx.file.configuration
|
||||
if hasattr(ctx.attr.configuration, "typescript"):
|
||||
configuration_file = ctx.attr.configuration.typescript.es5_sources.to_list()[0]
|
||||
|
||||
on_prepare_sources = []
|
||||
if ctx.file.on_prepare:
|
||||
on_prepare_sources = [ctx.file.on_prepare]
|
||||
if hasattr(ctx.attr.on_prepare, "node_sources"):
|
||||
on_prepare_sources = ctx.attr.on_prepare.node_sources.to_list()
|
||||
|
||||
on_prepare_file = ctx.file.on_prepare
|
||||
if hasattr(ctx.attr.on_prepare, "typescript"):
|
||||
on_prepare_file = ctx.attr.on_prepare.typescript.es5_sources.to_list()[0]
|
||||
|
||||
protractor_executable_path = ctx.executable.protractor.short_path
|
||||
if protractor_executable_path.startswith('..'):
|
||||
protractor_executable_path = "external" + protractor_executable_path[2:]
|
||||
|
||||
server_executable_path = ''
|
||||
if ctx.executable.server:
|
||||
server_executable_path = ctx.executable.server.short_path
|
||||
if server_executable_path.startswith('..'):
|
||||
server_executable_path = "external" + protractor_executable_path[2:]
|
||||
|
||||
ctx.actions.expand_template(
|
||||
output = configuration,
|
||||
template = ctx.file._conf_tmpl,
|
||||
substitutions = {
|
||||
"TMPL_config": expand_path_into_runfiles(ctx, configuration_file.short_path) if configuration_file else "",
|
||||
"TMPL_on_prepare": expand_path_into_runfiles(ctx, on_prepare_file.short_path) if on_prepare_file else "",
|
||||
"TMPL_workspace": ctx.workspace_name,
|
||||
"TMPL_server": server_executable_path,
|
||||
"TMPL_specs": "\n".join([" '%s'," % e for e in specs]),
|
||||
})
|
||||
|
||||
runfiles = [configuration] + configuration_sources + on_prepare_sources
|
||||
|
||||
ctx.actions.write(
|
||||
output = ctx.outputs.executable,
|
||||
is_executable = True,
|
||||
content = """#!/usr/bin/env bash
|
||||
if [ -e "$RUNFILE_MANIFEST_FILE" ]; then
|
||||
while read line; do
|
||||
declare -a PARTS=($line)
|
||||
if [ "${{PARTS[0]}}" == "angular/{TMPL_protractor}" ]; then
|
||||
readonly PROTRACTOR=${{PARTS[1]}}
|
||||
elif [ "${{PARTS[0]}}" == "angular/{TMPL_conf}" ]; then
|
||||
readonly CONF=${{PARTS[1]}}
|
||||
fi
|
||||
done < $RUNFILE_MANIFEST_FILE
|
||||
else
|
||||
readonly PROTRACTOR={TMPL_protractor}
|
||||
readonly CONF={TMPL_conf}
|
||||
fi
|
||||
|
||||
export HOME=$(mktemp -d)
|
||||
|
||||
# Print the protractor version in the test log
|
||||
PROTRACTOR_VERSION=$($PROTRACTOR --version)
|
||||
echo "Protractor $PROTRACTOR_VERSION"
|
||||
|
||||
# Run the protractor binary
|
||||
$PROTRACTOR $CONF
|
||||
""".format(TMPL_protractor = protractor_executable_path,
|
||||
TMPL_conf = configuration.short_path))
|
||||
return [DefaultInfo(
|
||||
files = depset([ctx.outputs.executable]),
|
||||
runfiles = ctx.runfiles(
|
||||
files = runfiles,
|
||||
transitive_files = files,
|
||||
# Propagate protractor_bin and its runfiles
|
||||
collect_data = True,
|
||||
collect_default = True,
|
||||
),
|
||||
executable = ctx.outputs.executable,
|
||||
)]
|
||||
|
||||
_protractor_web_test = rule(
|
||||
implementation = _protractor_web_test_impl,
|
||||
test = True,
|
||||
executable = True,
|
||||
attrs = {
|
||||
"configuration": attr.label(
|
||||
doc = "Protractor configuration file",
|
||||
allow_single_file = True,
|
||||
cfg = "data",
|
||||
aspects = [sources_aspect]),
|
||||
"srcs": attr.label_list(
|
||||
doc = "A list of JavaScript test files",
|
||||
allow_files = [".js"]),
|
||||
"on_prepare": attr.label(
|
||||
doc = """A file with a node.js script to run once before all tests run.
|
||||
If the script exports a function which returns a promise, protractor
|
||||
will wait for the promise to resolve before beginning tests.""",
|
||||
allow_single_file = True,
|
||||
cfg = "data",
|
||||
aspects = [sources_aspect]),
|
||||
"deps": attr.label_list(
|
||||
doc = "Other targets which produce JavaScript such as `ts_library`",
|
||||
allow_files = True,
|
||||
aspects = [sources_aspect]),
|
||||
"data": attr.label_list(
|
||||
doc = "Runtime dependencies",
|
||||
cfg = "data"),
|
||||
"server": attr.label(
|
||||
doc = "Optional server executable target",
|
||||
executable = True,
|
||||
cfg = "data",
|
||||
single_file = False,
|
||||
allow_files = True),
|
||||
"protractor": attr.label(
|
||||
doc = "Protractor executable target (set by protractor_web_test macro)",
|
||||
executable = True,
|
||||
cfg = "data",
|
||||
single_file = False,
|
||||
allow_files = True),
|
||||
"_conf_tmpl": attr.label(
|
||||
default = Label(_CONF_TMPL),
|
||||
allow_single_file = True,
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
def protractor_web_test(
|
||||
name,
|
||||
configuration = None,
|
||||
on_prepare = None,
|
||||
srcs = [],
|
||||
deps = [],
|
||||
data = [],
|
||||
server = None,
|
||||
tags = [],
|
||||
**kwargs):
|
||||
"""Runs a protractor test in a browser.
|
||||
|
||||
Args:
|
||||
name: The name of the test
|
||||
configuration: Protractor configuration file.
|
||||
on_prepare: A file with a node.js script to run once before all tests run.
|
||||
If the script exports a function which returns a promise, protractor
|
||||
will wait for the promise to resolve before beginning tests.
|
||||
srcs: JavaScript source files
|
||||
deps: Other targets which produce JavaScript such as `ts_library`
|
||||
data: Runtime dependencies
|
||||
server: Optional server executable target
|
||||
tags: Standard Bazel tags, this macro adds one for ibazel
|
||||
**kwargs: passed through to `_protractor_web_test`
|
||||
"""
|
||||
|
||||
protractor_bin_name = name + "_protractor_bin"
|
||||
|
||||
nodejs_binary(
|
||||
name = protractor_bin_name,
|
||||
entry_point = "protractor/bin/protractor",
|
||||
data = srcs + deps + data,
|
||||
node_modules = "@//:node_modules",
|
||||
testonly = 1,
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
# Our binary dependency must be in data[] for collect_data to pick it up
|
||||
# FIXME: maybe we can just ask :protractor_bin_name for its runfiles attr
|
||||
web_test_data = data + [":" + protractor_bin_name]
|
||||
if server:
|
||||
web_test_data += [server]
|
||||
|
||||
_protractor_web_test(
|
||||
name = name,
|
||||
configuration = configuration,
|
||||
on_prepare=on_prepare,
|
||||
srcs = srcs,
|
||||
deps = deps,
|
||||
data = web_test_data,
|
||||
server = server,
|
||||
protractor = protractor_bin_name,
|
||||
tags = tags + [
|
||||
# Users don't need to know that this tag is required to run under ibazel
|
||||
"ibazel_notify_changes",
|
||||
],
|
||||
**kwargs)
|
||||
|
||||
def protractor_web_test_suite(
|
||||
name,
|
||||
configuration = None,
|
||||
on_prepare = None,
|
||||
srcs = [],
|
||||
deps = [],
|
||||
data = [],
|
||||
server = None,
|
||||
browsers=["@io_bazel_rules_webtesting//browsers:chromium-local"],
|
||||
args=None,
|
||||
browser_overrides=None,
|
||||
config=None,
|
||||
flaky=None,
|
||||
local=None,
|
||||
shard_count=None,
|
||||
size=None,
|
||||
tags = [],
|
||||
test_suite_tags=None,
|
||||
timeout=None,
|
||||
visibility=None,
|
||||
web_test_data=[],
|
||||
wrapped_test_tags=None,
|
||||
**remaining_keyword_args):
|
||||
"""Defines a test_suite of web_test targets that wrap a protractor_web_test target.
|
||||
|
||||
Args:
|
||||
name: The base name of the test.
|
||||
configuration: Protractor configuration file.
|
||||
on_prepare: A file with a node.js script to run once before all tests run.
|
||||
If the script exports a function which returns a promise, protractor
|
||||
will wait for the promise to resolve before beginning tests.
|
||||
srcs: JavaScript source files
|
||||
deps: Other targets which produce JavaScript such as `ts_library`
|
||||
data: Runtime dependencies
|
||||
server: Optional server executable target
|
||||
browsers: A sequence of labels specifying the browsers to use.
|
||||
args: Args for web_test targets generated by this extension.
|
||||
browser_overrides: Dictionary; optional; default is an empty dictionary. A
|
||||
dictionary mapping from browser names to browser-specific web_test
|
||||
attributes, such as shard_count, flakiness, timeout, etc. For example:
|
||||
{'//browsers:chrome-native': {'shard_count': 3, 'flaky': 1}
|
||||
'//browsers:firefox-native': {'shard_count': 1, 'timeout': 100}}.
|
||||
config: Label; optional; Configuration of web test features.
|
||||
flaky: A boolean specifying that the test is flaky. If set, the test will
|
||||
be retried up to 3 times (default: 0)
|
||||
local: boolean; optional.
|
||||
shard_count: The number of test shards to use per browser. (default: 1)
|
||||
size: A string specifying the test size. (default: 'large')
|
||||
tags: A list of test tag strings to apply to each generated web_test target.
|
||||
This macro adds a couple for ibazel.
|
||||
test_suite_tags: A list of tag strings for the generated test_suite.
|
||||
timeout: A string specifying the test timeout (default: computed from size)
|
||||
visibility: List of labels; optional.
|
||||
web_test_data: Data dependencies for the web_test.
|
||||
wrapped_test_tags: A list of test tag strings to use for the wrapped test
|
||||
**remaining_keyword_args: Arguments for the wrapped test target.
|
||||
"""
|
||||
# Check explicitly for None so that users can set this to the empty list
|
||||
if wrapped_test_tags == None:
|
||||
wrapped_test_tags = DEFAULT_WRAPPED_TEST_TAGS
|
||||
|
||||
size = size or "large"
|
||||
|
||||
wrapped_test_name = name + "_wrapped_test"
|
||||
protractor_bin_name = name + "_protractor_bin"
|
||||
|
||||
# Users don't need to know that this tag is required to run under ibazel
|
||||
tags = tags + ["ibazel_notify_changes"]
|
||||
|
||||
nodejs_binary(
|
||||
name = protractor_bin_name,
|
||||
entry_point = "protractor/bin/protractor",
|
||||
data = srcs + deps + data,
|
||||
node_modules = "@//:node_modules",
|
||||
testonly = 1,
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
# Our binary dependency must be in data[] for collect_data to pick it up
|
||||
# FIXME: maybe we can just ask the :protractor_bin_name for its runfiles attr
|
||||
web_test_data = web_test_data + [":" + protractor_bin_name]
|
||||
if server:
|
||||
web_test_data += [server]
|
||||
|
||||
_protractor_web_test(
|
||||
name=wrapped_test_name,
|
||||
configuration=configuration,
|
||||
on_prepare=on_prepare,
|
||||
srcs=srcs,
|
||||
deps=deps,
|
||||
data=web_test_data,
|
||||
server=server,
|
||||
protractor=protractor_bin_name,
|
||||
args=args,
|
||||
flaky=flaky,
|
||||
local=local,
|
||||
shard_count=shard_count,
|
||||
size=size,
|
||||
tags=wrapped_test_tags,
|
||||
timeout=timeout,
|
||||
visibility=["//visibility:private"],
|
||||
**remaining_keyword_args)
|
||||
|
||||
web_test_suite(
|
||||
name=name,
|
||||
launcher=":"+wrapped_test_name,
|
||||
args=args,
|
||||
browsers=browsers,
|
||||
browser_overrides=browser_overrides,
|
||||
config=config,
|
||||
data=web_test_data,
|
||||
flaky=flaky,
|
||||
local=local,
|
||||
shard_count=shard_count,
|
||||
size=size,
|
||||
tags=tags,
|
||||
test=wrapped_test_name,
|
||||
test_suite_tags=test_suite_tags,
|
||||
timeout=timeout,
|
||||
visibility=visibility)
|
@ -1,16 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "package_assets",
|
||||
srcs = glob(["*"]),
|
||||
visibility = ["//packages/bazel:__subpackages__"],
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "utils",
|
||||
srcs = ["index.ts"],
|
||||
module_name = "@angular/bazel/protractor-utils",
|
||||
tsconfig = ":tsconfig.json",
|
||||
)
|
@ -1,94 +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
|
||||
*/
|
||||
|
||||
import * as child_process from 'child_process';
|
||||
import * as net from 'net';
|
||||
import * as path from 'path';
|
||||
|
||||
export function isTcpPortFree(port: number): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = net.createServer();
|
||||
server.on('error', (e) => { resolve(false); });
|
||||
server.on('close', () => { resolve(true); });
|
||||
server.listen(port, () => { server.close(); });
|
||||
});
|
||||
}
|
||||
|
||||
export function isTcpPortBound(port: number): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const client = new net.Socket();
|
||||
client.once('connect', () => { resolve(true); });
|
||||
client.once('error', (e) => { resolve(false); });
|
||||
client.connect(port);
|
||||
});
|
||||
}
|
||||
|
||||
export async function findFreeTcpPort(): Promise<number> {
|
||||
const range = {
|
||||
min: 32768,
|
||||
max: 60000,
|
||||
};
|
||||
for (let i = 0; i < 100; i++) {
|
||||
let port = Math.floor(Math.random() * (range.max - range.min) + range.min);
|
||||
if (await isTcpPortFree(port)) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
throw new Error('Unable to find a free port');
|
||||
}
|
||||
|
||||
// Interface for config parameter of the protractor_web_test_suite onPrepare function
|
||||
export interface OnPrepareConfig {
|
||||
// The workspace name
|
||||
workspace: string;
|
||||
|
||||
// The server binary to run
|
||||
server: string;
|
||||
}
|
||||
|
||||
export function waitForServer(port: number, timeout: number): Promise<boolean> {
|
||||
return isTcpPortBound(port).then(isBound => {
|
||||
if (!isBound) {
|
||||
if (timeout <= 0) {
|
||||
throw new Error('Timeout waiting for server to start');
|
||||
}
|
||||
const wait = Math.min(timeout, 500);
|
||||
return new Promise((res, rej) => setTimeout(res, wait))
|
||||
.then(() => waitForServer(port, timeout - wait));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Return type from runServer function
|
||||
export interface ServerSpec {
|
||||
// Port number that the server is running on
|
||||
port: number;
|
||||
}
|
||||
|
||||
export function runServer(
|
||||
workspace: string, binary: string, portFlag: string, args: string[],
|
||||
timeout = 5000): Promise<ServerSpec> {
|
||||
return findFreeTcpPort().then(function(port) {
|
||||
const runfiles_path = process.env.TEST_SRCDIR;
|
||||
const cmd = path.join(runfiles_path, workspace, binary);
|
||||
|
||||
args = args.concat([portFlag, port.toString()]);
|
||||
|
||||
const child = child_process.spawn(
|
||||
cmd, args, {cwd: path.join(runfiles_path, workspace), stdio: 'inherit'});
|
||||
|
||||
child.on('exit', function(code) {
|
||||
if (code != 0) {
|
||||
throw new Error(`non-zero exit code ${code} from server`);
|
||||
}
|
||||
});
|
||||
|
||||
return waitForServer(port, timeout).then(() => { return {port}; });
|
||||
});
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver", "ts_library")
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "rollup_bundle")
|
||||
load("//tools/http-server:http_server.bzl", "http_server")
|
||||
|
||||
ts_library(
|
||||
name = "app",
|
||||
srcs = ["app.ts"],
|
||||
)
|
||||
|
||||
ts_devserver(
|
||||
name = "devserver",
|
||||
serving_path = "/bundle.min.js",
|
||||
static_files = ["index.html"],
|
||||
deps = [":app"],
|
||||
)
|
||||
|
||||
rollup_bundle(
|
||||
name = "bundle",
|
||||
entry_point = "packages/bazel/test/protractor-2/app",
|
||||
deps = [":app"],
|
||||
)
|
||||
|
||||
http_server(
|
||||
name = "prodserver",
|
||||
data = [
|
||||
"index.html",
|
||||
":bundle",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "ts_spec",
|
||||
testonly = True,
|
||||
srcs = ["test.spec.ts"],
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "prodserver_test",
|
||||
configuration = ":conf.js",
|
||||
data = ["//packages/bazel/src/protractor/utils"],
|
||||
on_prepare = ":on-prepare.js",
|
||||
server = ":prodserver",
|
||||
deps = [":ts_spec"],
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "devserver_test",
|
||||
configuration = ":conf.js",
|
||||
data = ["//packages/bazel/src/protractor/utils"],
|
||||
on_prepare = ":on-prepare.js",
|
||||
server = ":prodserver",
|
||||
deps = [":ts_spec"],
|
||||
)
|
@ -1,12 +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
|
||||
*/
|
||||
|
||||
const el: HTMLDivElement = document.createElement('div');
|
||||
el.innerText = 'Hello, Protractor';
|
||||
el.className = 'ts1';
|
||||
document.body.appendChild(el);
|
@ -1,11 +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
|
||||
*/
|
||||
|
||||
exports.config = {
|
||||
onPrepare: function() { global.userOnPrepareGotCalled = true; }
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>protractor test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="/bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,22 +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
|
||||
*/
|
||||
|
||||
const protractorUtils = require('@angular/bazel/protractor-utils');
|
||||
const protractor = require('protractor');
|
||||
|
||||
module.exports = function(config) {
|
||||
if (!global.userOnPrepareGotCalled) {
|
||||
throw new Error('Expecting user configuration onPrepare to have been called');
|
||||
}
|
||||
const portFlag = config.server.endsWith('prodserver') ? '-p' : '-port';
|
||||
return protractorUtils.runServer(config.workspace, config.server, portFlag, [])
|
||||
.then(serverSpec => {
|
||||
const serverUrl = `http://localhost:${serverSpec.port}`;
|
||||
protractor.browser.baseUrl = serverUrl;
|
||||
});
|
||||
};
|
@ -1,28 +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
|
||||
*
|
||||
* @fileoverview A small demo of how to run a protractor test.
|
||||
*/
|
||||
|
||||
import {ExpectedConditions, browser, by, element} from 'protractor';
|
||||
|
||||
|
||||
// This test uses Protractor without Angular, so disable Angular features
|
||||
browser.waitForAngularEnabled(false);
|
||||
|
||||
describe('app', () => {
|
||||
beforeAll(() => {
|
||||
browser.get('');
|
||||
browser.wait(ExpectedConditions.presenceOf(element(by.css('div.ts1'))), 100000);
|
||||
});
|
||||
|
||||
it('should display: Hello, Protractor', (done) => {
|
||||
const div = element(by.css('div.ts1'));
|
||||
div.getText().then(t => expect(t).toEqual(`Hello, Protractor`));
|
||||
done();
|
||||
});
|
||||
});
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "ts_spec",
|
||||
testonly = True,
|
||||
srcs = ["test.spec.ts"],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "ts_conf",
|
||||
testonly = True,
|
||||
srcs = ["conf.ts"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = ["//packages/bazel/src/protractor/utils"],
|
||||
)
|
||||
|
||||
protractor_web_test_suite(
|
||||
name = "test",
|
||||
configuration = ":ts_conf",
|
||||
data = ["//packages/bazel/src/protractor/utils"],
|
||||
deps = [":ts_spec"],
|
||||
)
|
@ -1,30 +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
|
||||
*/
|
||||
|
||||
import * as protractorUtils from '@angular/bazel/protractor-utils';
|
||||
import {browser} from 'protractor';
|
||||
|
||||
const http = require('http');
|
||||
|
||||
exports.config = {
|
||||
onPrepare() {
|
||||
return protractorUtils.findFreeTcpPort().then(port => {
|
||||
const app = new http.Server();
|
||||
|
||||
app.on('request', (req, res) => {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.write('Hello World');
|
||||
res.end('\n');
|
||||
});
|
||||
|
||||
browser.baseUrl = `http://localhost:${port}`;
|
||||
|
||||
return new Promise(resolve => { app.listen(port, () => { resolve(); }); });
|
||||
});
|
||||
}
|
||||
};
|
@ -1,20 +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
|
||||
*
|
||||
* @fileoverview A small demo of how to run a protractor test.
|
||||
*/
|
||||
|
||||
import {$, browser} from 'protractor';
|
||||
|
||||
describe('Basic test', () => {
|
||||
it('should say hello world', () => {
|
||||
browser.waitForAngularEnabled(false);
|
||||
browser.get('/');
|
||||
|
||||
expect($('body').getText()).toContain('Hello World');
|
||||
});
|
||||
});
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
}
|
@ -29,7 +29,6 @@ ng_package(
|
||||
packages = ["//packages/common/locales:package"],
|
||||
tags = [
|
||||
"ivy-jit",
|
||||
"ivy-local",
|
||||
"release-with-framework",
|
||||
],
|
||||
deps = [
|
||||
|
@ -1,35 +0,0 @@
|
||||
load("//tools:defaults.bzl", "ts_library", "ts_web_test_suite")
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test")
|
||||
|
||||
ts_library(
|
||||
name = "test_lib",
|
||||
testonly = 1,
|
||||
srcs = glob(
|
||||
["**/*.ts"],
|
||||
exclude = ["**/*_node_only_spec.ts"],
|
||||
),
|
||||
deps = [
|
||||
"//packages/common/http",
|
||||
"//packages/common/http/testing",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"@rxjs",
|
||||
"@rxjs//operators",
|
||||
],
|
||||
)
|
||||
|
||||
jasmine_node_test(
|
||||
name = "test",
|
||||
bootstrap = ["angular/tools/testing/init_node_spec.js"],
|
||||
deps = [
|
||||
":test_lib",
|
||||
"//tools/testing:node",
|
||||
],
|
||||
)
|
||||
|
||||
ts_web_test_suite(
|
||||
name = "test_web",
|
||||
deps = [
|
||||
":test_lib",
|
||||
],
|
||||
)
|
@ -76,17 +76,13 @@ class SampleTokenExtractor {
|
||||
it('does not re-parse if document.cookie has not changed', () => {
|
||||
expect(extractor.getToken()).toEqual('test');
|
||||
expect(extractor.getToken()).toEqual('test');
|
||||
expect(getParseCount(extractor)).toEqual(1);
|
||||
expect(extractor.parseCount).toEqual(1);
|
||||
});
|
||||
it('re-parses if document.cookie changes', () => {
|
||||
expect(extractor.getToken()).toEqual('test');
|
||||
document['cookie'] = 'XSRF-TOKEN=blah';
|
||||
expect(extractor.getToken()).toEqual('blah');
|
||||
expect(getParseCount(extractor)).toEqual(2);
|
||||
expect(extractor.parseCount).toEqual(2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getParseCount(extractor: HttpXsrfCookieExtractor): number {
|
||||
return (extractor as any).parseCount;
|
||||
}
|
@ -193,9 +193,20 @@ function padNumber(
|
||||
return neg + strNum;
|
||||
}
|
||||
|
||||
function formatFractionalSeconds(milliseconds: number, digits: number): string {
|
||||
const strMs = padNumber(milliseconds, 3);
|
||||
return strMs.substr(0, digits);
|
||||
/**
|
||||
* Trim a fractional part to `digits` number of digits.
|
||||
* Right pads with "0" to fit the requested number of digits if needed.
|
||||
*
|
||||
* @param num The fractional part value
|
||||
* @param digits The width of the output
|
||||
*/
|
||||
function trimRPadFractional(num: number, digits: number): string {
|
||||
let strNum = String(num);
|
||||
// Add padding at the end
|
||||
while (strNum.length < digits) {
|
||||
strNum = strNum + 0;
|
||||
}
|
||||
return strNum.substr(0, digits);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,7 +226,7 @@ function dateGetter(
|
||||
part = 12;
|
||||
}
|
||||
} else if (name === DateType.FractionalSeconds) {
|
||||
return formatFractionalSeconds(part, size);
|
||||
return trimRPadFractional(part, size);
|
||||
}
|
||||
|
||||
const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
|
||||
|
@ -319,10 +319,6 @@ describe('Format date', () => {
|
||||
expect(formatDate(3000, 'm:ss.S', 'en')).toEqual('0:03.0');
|
||||
expect(formatDate(3000, 'm:ss.SS', 'en')).toEqual('0:03.00');
|
||||
expect(formatDate(3000, 'm:ss.SSS', 'en')).toEqual('0:03.000');
|
||||
expect(formatDate(3001, 'm:ss', 'en')).toEqual('0:03');
|
||||
expect(formatDate(3001, 'm:ss.S', 'en')).toEqual('0:03.0');
|
||||
expect(formatDate(3001, 'm:ss.SS', 'en')).toEqual('0:03.00');
|
||||
expect(formatDate(3001, 'm:ss.SSS', 'en')).toEqual('0:03.001');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -38,7 +38,6 @@ npm_package(
|
||||
],
|
||||
tags = [
|
||||
"ivy-jit",
|
||||
"ivy-local",
|
||||
"release-with-framework",
|
||||
],
|
||||
deps = [":compiler-cli"],
|
||||
|
@ -37,13 +37,10 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
}
|
||||
|
||||
analyze(node: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<NgModuleAnalysis> {
|
||||
if (decorator.args === null || decorator.args.length > 1) {
|
||||
if (decorator.args === null || decorator.args.length !== 1) {
|
||||
throw new Error(`Incorrect number of arguments to @NgModule decorator`);
|
||||
}
|
||||
|
||||
// @NgModule can be invoked without arguments. In case it is, pretend as if a blank object
|
||||
// literal was specified. This simplifies the code below.
|
||||
const meta = decorator.args.length === 1 ? decorator.args[0] : ts.createObjectLiteral([]);
|
||||
const meta = decorator.args[0];
|
||||
if (!ts.isObjectLiteralExpression(meta)) {
|
||||
throw new Error(`Decorator argument must be literal.`);
|
||||
}
|
||||
@ -135,12 +132,6 @@ function resolveTypeList(resolvedList: ResolvedValue, name: string): Reference[]
|
||||
}
|
||||
|
||||
resolvedList.forEach((entry, idx) => {
|
||||
// Unwrap ModuleWithProviders for modules that are locally declared (and thus static resolution
|
||||
// was able to descend into the function and return an object literal, a Map).
|
||||
if (entry instanceof Map && entry.has('ngModule')) {
|
||||
entry = entry.get('ngModule') !;
|
||||
}
|
||||
|
||||
if (Array.isArray(entry)) {
|
||||
// Recurse into nested arrays.
|
||||
refList.push(...resolveTypeList(entry, name));
|
||||
@ -153,7 +144,7 @@ function resolveTypeList(resolvedList: ResolvedValue, name: string): Reference[]
|
||||
refList.push(entry);
|
||||
} else {
|
||||
// TODO(alxhub): expand ModuleWithProviders.
|
||||
throw new Error(`Value at position ${idx} in ${name} array is not a reference: ${entry}`);
|
||||
throw new Error(`Value at position ${idx} in ${name} array is not a reference`);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -59,7 +59,7 @@ export class DtsFileTransformer {
|
||||
|
||||
const imports = this.imports.getAllImports(tsPath, this.coreImportsFrom);
|
||||
if (imports.length !== 0) {
|
||||
dts = imports.map(i => `import * as ${i.as} from '${i.name}';\n`).join('') + dts;
|
||||
dts = imports.map(i => `import * as ${i.as} from '${i.name}';\n`).join() + dts;
|
||||
}
|
||||
|
||||
return dts;
|
||||
|
@ -35,8 +35,8 @@ const CORE_SUPPORTED_SYMBOLS = new Set<string>([
|
||||
'ɵdefineNgModule',
|
||||
'inject',
|
||||
'InjectableDef',
|
||||
'ɵInjectorDef',
|
||||
'ɵNgModuleDef',
|
||||
'InjectorDef',
|
||||
'NgModuleDef',
|
||||
]);
|
||||
|
||||
export class ImportManager {
|
||||
|
@ -43,9 +43,8 @@ const EXPECTED_XMB = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!ELEMENT ex (#PCDATA)>
|
||||
]>
|
||||
<messagebundle>
|
||||
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/basic.html:1</source><source>src/comp2.ts:1</source><source>src/basic.html:1</source>translate me</msg>
|
||||
<msg id="9038505069473852515"><source>src/basic.html:3,4</source><source>src/comp2.ts:3,4</source><source>src/comp2.ts:2,3</source><source>src/basic.html:3,4</source>
|
||||
Welcome</msg>
|
||||
<msg id="8136548302122759730" desc="desc" meaning="meaning"><source>src/module.ts:1</source>translate me</msg>
|
||||
<msg id="3492007542396725315"><source>src/module.ts:2</source>Welcome</msg>
|
||||
</messagebundle>
|
||||
`;
|
||||
|
||||
@ -56,39 +55,18 @@ const EXPECTED_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<trans-unit id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" datatype="html">
|
||||
<source>translate me</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/basic.html</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/comp2.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/basic.html</context>
|
||||
<context context-type="sourcefile">src/module.ts</context>
|
||||
<context context-type="linenumber">1</context>
|
||||
</context-group>
|
||||
<note priority="1" from="description">desc</note>
|
||||
<note priority="1" from="meaning">meaning</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="085a5ecc40cc87451d216725b2befd50866de18a" datatype="html">
|
||||
<source>
|
||||
Welcome</source>
|
||||
<trans-unit id="65cc4ab3b4c438e07c89be2b677d08369fb62da2" datatype="html">
|
||||
<source>Welcome</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/basic.html</context>
|
||||
<context context-type="linenumber">3</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/comp2.ts</context>
|
||||
<context context-type="linenumber">3</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/comp2.ts</context>
|
||||
<context context-type="sourcefile">src/module.ts</context>
|
||||
<context context-type="linenumber">2</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/basic.html</context>
|
||||
<context context-type="linenumber">3</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
@ -102,24 +80,18 @@ const EXPECTED_XLIFF2 = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<notes>
|
||||
<note category="description">desc</note>
|
||||
<note category="meaning">meaning</note>
|
||||
<note category="location">src/basic.html:1</note>
|
||||
<note category="location">src/comp2.ts:1</note>
|
||||
<note category="location">src/basic.html:1</note>
|
||||
<note category="location">src/module.ts:1</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translate me</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="9038505069473852515">
|
||||
<unit id="3492007542396725315">
|
||||
<notes>
|
||||
<note category="location">src/basic.html:3,4</note>
|
||||
<note category="location">src/comp2.ts:3,4</note>
|
||||
<note category="location">src/comp2.ts:2,3</note>
|
||||
<note category="location">src/basic.html:3,4</note>
|
||||
<note category="location">src/module.ts:2</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>
|
||||
Welcome</source>
|
||||
<source>Welcome</source>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
@ -183,54 +155,21 @@ describe('extract_i18n command line', () => {
|
||||
});
|
||||
|
||||
function writeSources() {
|
||||
const welcomeMessage = `
|
||||
<!--i18n-->
|
||||
Welcome<!--/i18n-->
|
||||
`;
|
||||
write('src/basic.html', `<div title="translate me" i18n-title="meaning|desc"></div>
|
||||
<p id="welcomeMessage">${welcomeMessage}</p>`);
|
||||
|
||||
write('src/comp1.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
write('src/basic.html', [
|
||||
`<div title="translate me" i18n-title="meaning|desc"></div>`,
|
||||
`<p id="welcomeMessage"><!--i18n-->Welcome<!--/i18n--></p>`,
|
||||
].join('\n'));
|
||||
write('src/module.ts', `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'basic',
|
||||
templateUrl: './basic.html',
|
||||
})
|
||||
export class BasicCmp1 {}`);
|
||||
|
||||
write('src/comp2.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'basic2',
|
||||
template: \`<div title="translate me" i18n-title="meaning|desc"></div>
|
||||
<p id="welcomeMessage">${welcomeMessage}</p>\`,
|
||||
})
|
||||
export class BasicCmp2 {}
|
||||
@Component({
|
||||
selector: 'basic4',
|
||||
template: \`<p id="welcomeMessage">${welcomeMessage}</p>\`,
|
||||
})
|
||||
export class BasicCmp4 {}`);
|
||||
|
||||
write('src/comp3.ts', `
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'basic3',
|
||||
templateUrl: './basic.html',
|
||||
})
|
||||
export class BasicCmp3 {}`);
|
||||
|
||||
write('src/module.ts', `
|
||||
import {NgModule} from '@angular/core';
|
||||
import {BasicCmp1} from './comp1';
|
||||
import {BasicCmp2, BasicCmp4} from './comp2';
|
||||
import {BasicCmp3} from './comp3';
|
||||
export class BasicCmp {}
|
||||
|
||||
@NgModule({
|
||||
declarations: [BasicCmp1, BasicCmp2, BasicCmp3, BasicCmp4]
|
||||
declarations: [BasicCmp]
|
||||
})
|
||||
export class I18nModule {}
|
||||
`);
|
||||
|
@ -144,7 +144,7 @@ describe('ngtsc behavioral tests', () => {
|
||||
expect(jsContents).not.toContain('__decorate');
|
||||
|
||||
const dtsContents = getContents('test.d.ts');
|
||||
expect(dtsContents).toContain('static ngComponentDef: i0.ɵComponentDef<TestCmp, \'test-cmp\'>');
|
||||
expect(dtsContents).toContain('static ngComponentDef: i0.ComponentDef<TestCmp, \'test-cmp\'>');
|
||||
});
|
||||
|
||||
it('should compile Components without errors', () => {
|
||||
@ -196,9 +196,9 @@ describe('ngtsc behavioral tests', () => {
|
||||
'declarations: [TestCmp], imports: [], exports: [] })');
|
||||
|
||||
const dtsContents = getContents('test.d.ts');
|
||||
expect(dtsContents).toContain('static ngComponentDef: i0.ɵComponentDef<TestCmp, \'test-cmp\'>');
|
||||
expect(dtsContents).toContain('static ngComponentDef: i0.ComponentDef<TestCmp, \'test-cmp\'>');
|
||||
expect(dtsContents)
|
||||
.toContain('static ngModuleDef: i0.ɵNgModuleDef<TestModule, [TestCmp], [], []>');
|
||||
.toContain('static ngModuleDef: i0.NgModuleDef<TestModule, [TestCmp], [], []>');
|
||||
expect(dtsContents).not.toContain('__decorate');
|
||||
});
|
||||
|
||||
@ -240,8 +240,8 @@ describe('ngtsc behavioral tests', () => {
|
||||
|
||||
const dtsContents = getContents('test.d.ts');
|
||||
expect(dtsContents)
|
||||
.toContain('static ngModuleDef: i0.ɵNgModuleDef<TestModule, [TestCmp], [OtherModule], []>');
|
||||
expect(dtsContents).toContain('static ngInjectorDef: i0.ɵInjectorDef');
|
||||
.toContain('static ngModuleDef: i0.NgModuleDef<TestModule, [TestCmp], [OtherModule], []>');
|
||||
expect(dtsContents).toContain('static ngInjectorDef: i0.InjectorDef');
|
||||
});
|
||||
|
||||
it('should compile Pipes without errors', () => {
|
||||
@ -342,6 +342,6 @@ describe('ngtsc behavioral tests', () => {
|
||||
expect(jsContents).toContain('pipes: [TestPipe]');
|
||||
|
||||
const dtsContents = getContents('test.d.ts');
|
||||
expect(dtsContents).toContain('i0.ɵNgModuleDef<TestModule, [TestPipe,TestCmp], [], []>');
|
||||
expect(dtsContents).toContain('i0.NgModuleDef<TestModule, [TestPipe,TestCmp], [], []>');
|
||||
});
|
||||
});
|
||||
|
@ -23,7 +23,6 @@ ng_package(
|
||||
include_devmode_srcs = True,
|
||||
tags = [
|
||||
"ivy-jit",
|
||||
"ivy-local",
|
||||
"release-with-framework",
|
||||
],
|
||||
deps = [
|
||||
|
@ -318,12 +318,10 @@ export class AotCompiler {
|
||||
});
|
||||
compMetas.forEach(compMeta => {
|
||||
const html = compMeta.template !.template !;
|
||||
// Template URL points to either an HTML or TS file depending on whether
|
||||
// the file is used with `templateUrl:` or `template:`, respectively.
|
||||
const templateUrl = compMeta.template !.templateUrl !;
|
||||
const interpolationConfig =
|
||||
InterpolationConfig.fromArray(compMeta.template !.interpolation);
|
||||
errors.push(...messageBundle.updateFromTemplate(html, templateUrl, interpolationConfig) !);
|
||||
errors.push(
|
||||
...messageBundle.updateFromTemplate(html, file.fileName, interpolationConfig) !);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -380,6 +380,8 @@ export const enum RenderFlags {
|
||||
Update = 0b10
|
||||
}
|
||||
|
||||
// Note this will expand once `class` is introduced to styling
|
||||
export const enum InitialStylingFlags {
|
||||
VALUES_MODE = 0b1,
|
||||
/** Mode for matching initial style values */
|
||||
INITIAL_STYLES = 0b00,
|
||||
}
|
||||
|
@ -75,14 +75,10 @@ export class Extractor {
|
||||
});
|
||||
compMetas.forEach(compMeta => {
|
||||
const html = compMeta.template !.template !;
|
||||
// Template URL points to either an HTML or TS file depending on
|
||||
// whether the file is used with `templateUrl:` or `template:`,
|
||||
// respectively.
|
||||
const templateUrl = compMeta.template !.templateUrl !;
|
||||
const interpolationConfig =
|
||||
InterpolationConfig.fromArray(compMeta.template !.interpolation);
|
||||
errors.push(...this.messageBundle.updateFromTemplate(
|
||||
html, templateUrl, interpolationConfig) !);
|
||||
html, file.fileName, interpolationConfig) !);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -33,11 +33,13 @@ export class Identifiers {
|
||||
|
||||
static elementAttribute: o.ExternalReference = {name: 'ɵa', moduleName: CORE};
|
||||
|
||||
static elementClassProp: o.ExternalReference = {name: 'ɵcp', moduleName: CORE};
|
||||
static elementClass: o.ExternalReference = {name: 'ɵk', moduleName: CORE};
|
||||
|
||||
static elementClassNamed: o.ExternalReference = {name: 'ɵkn', moduleName: CORE};
|
||||
|
||||
static elementStyling: o.ExternalReference = {name: 'ɵs', moduleName: CORE};
|
||||
|
||||
static elementStylingMap: o.ExternalReference = {name: 'ɵsm', moduleName: CORE};
|
||||
static elementStyle: o.ExternalReference = {name: 'ɵsm', moduleName: CORE};
|
||||
|
||||
static elementStyleProp: o.ExternalReference = {name: 'ɵsp', moduleName: CORE};
|
||||
|
||||
@ -102,7 +104,7 @@ export class Identifiers {
|
||||
static defineComponent: o.ExternalReference = {name: 'ɵdefineComponent', moduleName: CORE};
|
||||
|
||||
static ComponentDef: o.ExternalReference = {
|
||||
name: 'ɵComponentDef',
|
||||
name: 'ComponentDef',
|
||||
moduleName: CORE,
|
||||
};
|
||||
|
||||
@ -112,12 +114,12 @@ export class Identifiers {
|
||||
};
|
||||
|
||||
static DirectiveDef: o.ExternalReference = {
|
||||
name: 'ɵDirectiveDef',
|
||||
name: 'DirectiveDef',
|
||||
moduleName: CORE,
|
||||
};
|
||||
|
||||
static InjectorDef: o.ExternalReference = {
|
||||
name: 'ɵInjectorDef',
|
||||
name: 'InjectorDef',
|
||||
moduleName: CORE,
|
||||
};
|
||||
|
||||
@ -127,7 +129,7 @@ export class Identifiers {
|
||||
};
|
||||
|
||||
static NgModuleDef: o.ExternalReference = {
|
||||
name: 'ɵNgModuleDef',
|
||||
name: 'NgModuleDef',
|
||||
moduleName: CORE,
|
||||
};
|
||||
|
||||
|
@ -107,8 +107,7 @@ export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
|
||||
providers: meta.providers,
|
||||
imports: meta.imports,
|
||||
})]);
|
||||
const type =
|
||||
new o.ExpressionType(o.importExpr(R3.InjectorDef, [new o.ExpressionType(meta.type)]));
|
||||
const type = new o.ExpressionType(o.importExpr(R3.InjectorDef));
|
||||
return {expression, type};
|
||||
}
|
||||
|
||||
|
@ -88,14 +88,9 @@ export function compileDirectiveFromMetadata(
|
||||
bindingParser: BindingParser): R3DirectiveDef {
|
||||
const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
|
||||
const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]);
|
||||
|
||||
// On the type side, remove newlines from the selector as it will need to fit into a TypeScript
|
||||
// string literal, which must be on one line.
|
||||
const selectorForType = (meta.selector || '').replace(/\n/g, '');
|
||||
|
||||
const type = new o.ExpressionType(o.importExpr(
|
||||
R3.DirectiveDef,
|
||||
[new o.ExpressionType(meta.type), new o.ExpressionType(o.literal(selectorForType))]));
|
||||
[new o.ExpressionType(meta.type), new o.ExpressionType(o.literal(meta.selector || ''))]));
|
||||
return {expression, type};
|
||||
}
|
||||
|
||||
@ -162,14 +157,10 @@ export function compileComponentFromMetadata(
|
||||
definitionMap.set('pipes', o.literalArr(Array.from(pipesUsed)));
|
||||
}
|
||||
|
||||
// On the type side, remove newlines from the selector as it will need to fit into a TypeScript
|
||||
// string literal, which must be on one line.
|
||||
const selectorForType = (meta.selector || '').replace(/\n/g, '');
|
||||
|
||||
const expression = o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()]);
|
||||
const type = new o.ExpressionType(o.importExpr(
|
||||
R3.ComponentDef,
|
||||
[new o.ExpressionType(meta.type), new o.ExpressionType(o.literal(selectorForType))]));
|
||||
[new o.ExpressionType(meta.type), new o.ExpressionType(o.literal(meta.selector || ''))]));
|
||||
|
||||
return {expression, type};
|
||||
}
|
||||
|
@ -40,12 +40,19 @@ function mapBindingToInstruction(type: BindingType): o.ExternalReference|undefin
|
||||
case BindingType.Attribute:
|
||||
return R3.elementAttribute;
|
||||
case BindingType.Class:
|
||||
return R3.elementClassProp;
|
||||
return R3.elementClassNamed;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// `className` is used below instead of `class` because the interception
|
||||
// code (where this map is used) deals with DOM element property values
|
||||
// (like elm.propName) and not component bindining properties (like [propName]).
|
||||
const SPECIAL_CASED_PROPERTIES_INSTRUCTION_MAP: {[index: string]: o.ExternalReference} = {
|
||||
'className': R3.elementClass
|
||||
};
|
||||
|
||||
export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver {
|
||||
private _dataIndex = 0;
|
||||
private _bindingContext = 0;
|
||||
@ -303,59 +310,33 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
const i18nMessages: o.Statement[] = [];
|
||||
const attributes: o.Expression[] = [];
|
||||
const initialStyleDeclarations: o.Expression[] = [];
|
||||
const initialClassDeclarations: o.Expression[] = [];
|
||||
|
||||
const styleInputs: t.BoundAttribute[] = [];
|
||||
const classInputs: t.BoundAttribute[] = [];
|
||||
const allOtherInputs: t.BoundAttribute[] = [];
|
||||
|
||||
element.inputs.forEach((input: t.BoundAttribute) => {
|
||||
switch (input.type) {
|
||||
// [attr.style] or [attr.class] should not be treated as styling-based
|
||||
// bindings since they are intended to be written directly to the attr
|
||||
// and therefore will skip all style/class resolution that is present
|
||||
// with style="", [style]="" and [style.prop]="", class="",
|
||||
// [class.prop]="". [class]="" assignments
|
||||
case BindingType.Property:
|
||||
if (input.name == 'style') {
|
||||
// this should always go first in the compilation (for [style])
|
||||
styleInputs.splice(0, 0, input);
|
||||
} else if (isClassBinding(input)) {
|
||||
// this should always go first in the compilation (for [class])
|
||||
classInputs.splice(0, 0, input);
|
||||
} else {
|
||||
allOtherInputs.push(input);
|
||||
}
|
||||
break;
|
||||
case BindingType.Style:
|
||||
styleInputs.push(input);
|
||||
break;
|
||||
case BindingType.Class:
|
||||
classInputs.push(input);
|
||||
break;
|
||||
default:
|
||||
allOtherInputs.push(input);
|
||||
break;
|
||||
// [attr.style] should not be treated as a styling-based
|
||||
// binding since it is intended to write directly to the attr
|
||||
// and therefore will skip all style resolution that is present
|
||||
// with style="", [style]="" and [style.prop]="" assignments
|
||||
if (input.name == 'style' && input.type == BindingType.Property) {
|
||||
// this should always go first in the compilation (for [style])
|
||||
styleInputs.splice(0, 0, input);
|
||||
} else if (input.type == BindingType.Style) {
|
||||
styleInputs.push(input);
|
||||
} else {
|
||||
allOtherInputs.push(input);
|
||||
}
|
||||
});
|
||||
|
||||
let currStyleIndex = 0;
|
||||
let currClassIndex = 0;
|
||||
let staticStylesMap: {[key: string]: any}|null = null;
|
||||
let staticClassesMap: {[key: string]: boolean}|null = null;
|
||||
const stylesIndexMap: {[key: string]: number} = {};
|
||||
const classesIndexMap: {[key: string]: number} = {};
|
||||
Object.getOwnPropertyNames(outputAttrs).forEach(name => {
|
||||
const value = outputAttrs[name];
|
||||
if (name == 'style') {
|
||||
staticStylesMap = parseStyle(value);
|
||||
Object.keys(staticStylesMap).forEach(prop => { stylesIndexMap[prop] = currStyleIndex++; });
|
||||
} else if (name == 'class') {
|
||||
staticClassesMap = {};
|
||||
value.split(/\s+/g).forEach(className => {
|
||||
classesIndexMap[className] = currClassIndex++;
|
||||
staticClassesMap ![className] = true;
|
||||
});
|
||||
} else {
|
||||
attributes.push(o.literal(name));
|
||||
if (attrI18nMetas.hasOwnProperty(name)) {
|
||||
@ -376,14 +357,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < classInputs.length; i++) {
|
||||
const input = classInputs[i];
|
||||
const isMapBasedClassBinding = i === 0 && isClassBinding(input);
|
||||
if (!isMapBasedClassBinding && !stylesIndexMap.hasOwnProperty(input.name)) {
|
||||
classesIndexMap[input.name] = currClassIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// this will build the instructions so that they fall into the following syntax
|
||||
// => [prop1, prop2, prop3, 0, prop1, value1, prop2, value2]
|
||||
Object.keys(stylesIndexMap).forEach(prop => {
|
||||
@ -391,7 +364,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
});
|
||||
|
||||
if (staticStylesMap) {
|
||||
initialStyleDeclarations.push(o.literal(core.InitialStylingFlags.VALUES_MODE));
|
||||
initialStyleDeclarations.push(o.literal(core.InitialStylingFlags.INITIAL_STYLES));
|
||||
|
||||
Object.keys(staticStylesMap).forEach(prop => {
|
||||
initialStyleDeclarations.push(o.literal(prop));
|
||||
@ -400,22 +373,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(classesIndexMap).forEach(prop => {
|
||||
initialClassDeclarations.push(o.literal(prop));
|
||||
});
|
||||
|
||||
if (staticClassesMap) {
|
||||
initialClassDeclarations.push(o.literal(core.InitialStylingFlags.VALUES_MODE));
|
||||
|
||||
Object.keys(staticClassesMap).forEach(className => {
|
||||
initialClassDeclarations.push(o.literal(className));
|
||||
initialClassDeclarations.push(o.literal(true));
|
||||
});
|
||||
}
|
||||
|
||||
const hasStylingInstructions = initialStyleDeclarations.length || styleInputs.length ||
|
||||
initialClassDeclarations.length || classInputs.length;
|
||||
|
||||
const attrArg: o.Expression = attributes.length > 0 ?
|
||||
this.constantPool.getConstLiteral(o.literalArr(attributes), true) :
|
||||
o.TYPED_NULL_EXPR;
|
||||
@ -454,8 +411,10 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
|
||||
const implicit = o.variable(CONTEXT_NAME);
|
||||
|
||||
const elementStyleIndex =
|
||||
(initialStyleDeclarations.length || styleInputs.length) ? this.allocateDataSlot() : 0;
|
||||
const createSelfClosingInstruction =
|
||||
!hasStylingInstructions && element.children.length === 0 && element.outputs.length === 0;
|
||||
elementStyleIndex === 0 && element.children.length === 0 && element.outputs.length === 0;
|
||||
|
||||
if (createSelfClosingInstruction) {
|
||||
this.instruction(
|
||||
@ -470,30 +429,16 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
...trimTrailingNulls(parameters));
|
||||
|
||||
// initial styling for static style="..." attributes
|
||||
if (hasStylingInstructions) {
|
||||
const paramsList: (o.Expression)[] = [];
|
||||
|
||||
if (elementStyleIndex > 0) {
|
||||
let paramsList: (o.Expression)[] = [o.literal(elementStyleIndex)];
|
||||
if (initialStyleDeclarations.length) {
|
||||
// the template compiler handles initial style (e.g. style="foo") values
|
||||
// the template compiler handles initial styling (e.g. style="foo") values
|
||||
// in a special command called `elementStyle` so that the initial styles
|
||||
// can be processed during runtime. These initial styles values are bound to
|
||||
// a constant because the inital style values do not change (since they're static).
|
||||
paramsList.push(
|
||||
this.constantPool.getConstLiteral(o.literalArr(initialStyleDeclarations), true));
|
||||
} else if (initialClassDeclarations.length) {
|
||||
// no point in having an extra `null` value unless there are follow-up params
|
||||
paramsList.push(o.NULL_EXPR);
|
||||
}
|
||||
|
||||
if (initialClassDeclarations.length) {
|
||||
// the template compiler handles initial class styling (e.g. class="foo") values
|
||||
// in a special command called `elementClass` so that the initial class
|
||||
// can be processed during runtime. These initial class values are bound to
|
||||
// a constant because the inital class values do not change (since they're static).
|
||||
paramsList.push(
|
||||
this.constantPool.getConstLiteral(o.literalArr(initialClassDeclarations), true));
|
||||
}
|
||||
|
||||
this._creationCode.push(o.importExpr(R3.elementStyling).callFn(paramsList).toStmt());
|
||||
}
|
||||
|
||||
@ -520,74 +465,46 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
});
|
||||
}
|
||||
|
||||
if ((styleInputs.length || classInputs.length) && hasStylingInstructions) {
|
||||
const indexLiteral = o.literal(elementIndex);
|
||||
|
||||
const firstStyle = styleInputs[0];
|
||||
const mapBasedStyleInput = firstStyle && firstStyle.name == 'style' ? firstStyle : null;
|
||||
|
||||
const firstClass = classInputs[0];
|
||||
const mapBasedClassInput = firstClass && isClassBinding(firstClass) ? firstClass : null;
|
||||
|
||||
const stylingInput = mapBasedStyleInput || mapBasedClassInput;
|
||||
if (stylingInput) {
|
||||
const params: o.Expression[] = [];
|
||||
if (mapBasedStyleInput) {
|
||||
params.push(this.convertPropertyBinding(implicit, mapBasedStyleInput.value, true));
|
||||
} else if (mapBasedClassInput) {
|
||||
params.push(o.NULL_EXPR);
|
||||
}
|
||||
if (mapBasedClassInput) {
|
||||
params.push(this.convertPropertyBinding(implicit, mapBasedClassInput.value, true));
|
||||
}
|
||||
this.instruction(
|
||||
this._bindingCode, stylingInput.sourceSpan, R3.elementStylingMap, indexLiteral,
|
||||
...params);
|
||||
}
|
||||
|
||||
let lastInputCommand: t.BoundAttribute|null = null;
|
||||
if (styleInputs.length) {
|
||||
let i = mapBasedStyleInput ? 1 : 0;
|
||||
for (i; i < styleInputs.length; i++) {
|
||||
const input = styleInputs[i];
|
||||
const convertedBinding = this.convertPropertyBinding(implicit, input.value, true);
|
||||
if (styleInputs.length && elementStyleIndex > 0) {
|
||||
const indexLiteral = o.literal(elementStyleIndex);
|
||||
styleInputs.forEach((input, i) => {
|
||||
const isMapBasedStyleBinding = i == 0 && input.name == 'style';
|
||||
const convertedBinding = this.convertPropertyBinding(implicit, input.value, true);
|
||||
if (isMapBasedStyleBinding) {
|
||||
this.instruction(
|
||||
this._bindingCode, input.sourceSpan, R3.elementStyle, indexLiteral, convertedBinding);
|
||||
} else {
|
||||
const key = input.name;
|
||||
const styleIndex: number = stylesIndexMap[key] !;
|
||||
let styleIndex: number = stylesIndexMap[key] !;
|
||||
this.instruction(
|
||||
this._bindingCode, input.sourceSpan, R3.elementStyleProp, indexLiteral,
|
||||
o.literal(styleIndex), convertedBinding);
|
||||
}
|
||||
});
|
||||
|
||||
lastInputCommand = styleInputs[styleInputs.length - 1];
|
||||
}
|
||||
|
||||
if (classInputs.length) {
|
||||
let i = mapBasedClassInput ? 1 : 0;
|
||||
for (i; i < classInputs.length; i++) {
|
||||
const input = classInputs[i];
|
||||
const convertedBinding = this.convertPropertyBinding(implicit, input.value, true);
|
||||
const key = input.name;
|
||||
const classIndex: number = classesIndexMap[key] !;
|
||||
this.instruction(
|
||||
this._bindingCode, input.sourceSpan, R3.elementClassProp, indexLiteral,
|
||||
o.literal(classIndex), convertedBinding);
|
||||
}
|
||||
|
||||
lastInputCommand = classInputs[classInputs.length - 1];
|
||||
}
|
||||
|
||||
this.instruction(
|
||||
this._bindingCode, lastInputCommand !.sourceSpan, R3.elementStylingApply, indexLiteral);
|
||||
const spanEnd = styleInputs[styleInputs.length - 1].sourceSpan;
|
||||
this.instruction(this._bindingCode, spanEnd, R3.elementStylingApply, indexLiteral);
|
||||
}
|
||||
|
||||
// Generate element input bindings
|
||||
allOtherInputs.forEach((input: t.BoundAttribute) => {
|
||||
if (input.type === BindingType.Animation) {
|
||||
console.error('warning: animation bindings not yet supported');
|
||||
return;
|
||||
this._unsupported('animations');
|
||||
}
|
||||
|
||||
const convertedBinding = this.convertPropertyBinding(implicit, input.value);
|
||||
const specialInstruction = SPECIAL_CASED_PROPERTIES_INSTRUCTION_MAP[input.name];
|
||||
if (specialInstruction) {
|
||||
// special case for [style] and [class] bindings since they are not handled as
|
||||
// standard properties within this implementation. Instead they are
|
||||
// handed off to special cased instruction handlers which will then
|
||||
// delegate them as animation sequences (or input bindings for dirs/cmps)
|
||||
this.instruction(
|
||||
this._bindingCode, input.sourceSpan, specialInstruction, o.literal(elementIndex),
|
||||
convertedBinding);
|
||||
return;
|
||||
}
|
||||
|
||||
const instruction = mapBindingToInstruction(input.type);
|
||||
if (instruction) {
|
||||
// TODO(chuckj): runtime: security context?
|
||||
@ -1057,7 +974,3 @@ export function makeBindingParser(): BindingParser {
|
||||
new Parser(new Lexer()), DEFAULT_INTERPOLATION_CONFIG, new DomElementSchemaRegistry(), null,
|
||||
[]);
|
||||
}
|
||||
|
||||
function isClassBinding(input: t.BoundAttribute): boolean {
|
||||
return input.name == 'className' || input.name == 'class';
|
||||
}
|
||||
|
@ -6,12 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {InitialStylingFlags} from '../../src/core';
|
||||
import {MockDirectory, setup} from '../aot/test_util';
|
||||
|
||||
import {compile, expectEmit} from './mock_compile';
|
||||
|
||||
|
||||
/* These tests are codified version of the tests in compiler_canonical_spec.ts. Every
|
||||
* test in compiler_canonical_spec.ts should have a corresponding test here.
|
||||
*/
|
||||
@ -47,17 +44,15 @@ describe('compiler compliance', () => {
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ['title', 'Hello'];
|
||||
const $c2$ = ['my-app', ${InitialStylingFlags.VALUES_MODE}, 'my-app', true];
|
||||
const $c3$ = ['cx', '20', 'cy', '30', 'r', '50'];
|
||||
const $c1$ = ['class', 'my-app', 'title', 'Hello'];
|
||||
const $c2$ = ['cx', '20', 'cy', '30', 'r', '50'];
|
||||
…
|
||||
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div', $c1$);
|
||||
$r3$.ɵs((null as any), $c2$);
|
||||
$r3$.ɵNS();
|
||||
$r3$.ɵE(1, 'svg');
|
||||
$r3$.ɵEe(2, 'circle', $c3$);
|
||||
$r3$.ɵEe(2, 'circle', $c2$);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵNH();
|
||||
$r3$.ɵE(3, 'p');
|
||||
@ -98,13 +93,11 @@ describe('compiler compliance', () => {
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ['title', 'Hello'];
|
||||
const $c2$ = ['my-app', ${InitialStylingFlags.VALUES_MODE}, 'my-app', true];
|
||||
const $c1$ = ['class', 'my-app', 'title', 'Hello'];
|
||||
…
|
||||
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div', $c1$);
|
||||
$r3$.ɵs((null as any), $c2$);
|
||||
$r3$.ɵNM();
|
||||
$r3$.ɵE(1, 'math');
|
||||
$r3$.ɵEe(2, 'infinity');
|
||||
@ -148,13 +141,11 @@ describe('compiler compliance', () => {
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ['title', 'Hello'];
|
||||
const $c2$ = ['my-app', ${InitialStylingFlags.VALUES_MODE}, 'my-app', true];
|
||||
const $c1$ = ['class', 'my-app', 'title', 'Hello'];
|
||||
…
|
||||
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div', $c1$);
|
||||
$r3$.ɵs((null as any), $c2$);
|
||||
$r3$.ɵT(1, 'Hello ');
|
||||
$r3$.ɵE(2, 'b');
|
||||
$r3$.ɵT(3, 'World');
|
||||
@ -331,7 +322,6 @@ describe('compiler compliance', () => {
|
||||
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
|
||||
const template = `
|
||||
const _c0 = ['background-color'];
|
||||
const _c1 = ['error'];
|
||||
class MyComponent {
|
||||
static ngComponentDef = i0.ɵdefineComponent({type:MyComponent,selectors:[['my-component']],
|
||||
factory:function MyComponent_Factory(){
|
||||
@ -339,13 +329,13 @@ describe('compiler compliance', () => {
|
||||
},template:function MyComponent_Template(rf:number,ctx:any){
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div');
|
||||
$r3$.ɵs(_c0, _c1);
|
||||
$r3$.ɵs(1, _c0);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵsp(0, 0, ctx.color);
|
||||
$r3$.ɵcp(0, 0, ctx.error);
|
||||
$r3$.ɵsa(0);
|
||||
$r3$.ɵsp(1, 0, ctx.color);
|
||||
$r3$.ɵsa(1);
|
||||
$r3$.ɵkn(0, 'error', $r3$.ɵb(ctx.error));
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -43,12 +43,12 @@ describe('compiler compliance: styling', () => {
|
||||
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div');
|
||||
$r3$.ɵs();
|
||||
$r3$.ɵs(1);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵsm(0, $ctx$.myStyleExp);
|
||||
$r3$.ɵsa(0);
|
||||
$r3$.ɵsm(1, $ctx$.myStyleExp);
|
||||
$r3$.ɵsa(1);
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -57,7 +57,7 @@ describe('compiler compliance: styling', () => {
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should place initial, multi, singular and application followed by attribute style instructions in the template code in that order',
|
||||
it('should place initial, multi, singular and application followed by attribute styling instructions in the template code in that order',
|
||||
() => {
|
||||
const files = {
|
||||
app: {
|
||||
@ -85,7 +85,7 @@ describe('compiler compliance: styling', () => {
|
||||
};
|
||||
|
||||
const template = `
|
||||
const _c0 = ['opacity','width','height',${InitialStylingFlags.VALUES_MODE},'opacity','1'];
|
||||
const _c0 = ['opacity','width','height',${InitialStylingFlags.INITIAL_STYLES},'opacity','1'];
|
||||
class MyComponent {
|
||||
static ngComponentDef = i0.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
@ -96,14 +96,14 @@ describe('compiler compliance: styling', () => {
|
||||
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div');
|
||||
$r3$.ɵs(_c0);
|
||||
$r3$.ɵs(1, _c0);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵsm(0, $ctx$.myStyleExp);
|
||||
$r3$.ɵsp(0, 1, $ctx$.myWidth);
|
||||
$r3$.ɵsp(0, 2, $ctx$.myHeight);
|
||||
$r3$.ɵsa(0);
|
||||
$r3$.ɵsm(1, $ctx$.myStyleExp);
|
||||
$r3$.ɵsp(1, 1, $ctx$.myWidth);
|
||||
$r3$.ɵsp(1, 2, $ctx$.myHeight);
|
||||
$r3$.ɵsa(1);
|
||||
$r3$.ɵa(0, 'style', $r3$.ɵb('border-width: 10px'));
|
||||
}
|
||||
}
|
||||
@ -127,7 +127,7 @@ describe('compiler compliance: styling', () => {
|
||||
template: \`<div [class]="myClassExp"></div>\`
|
||||
})
|
||||
export class MyComponent {
|
||||
myClassExp = {'foo':true}
|
||||
myClassExp = [{color:'orange'}, {color:'green', duration:1000}]
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
@ -139,13 +139,10 @@ describe('compiler compliance: styling', () => {
|
||||
const template = `
|
||||
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div');
|
||||
$r3$.ɵs();
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵEe(0, 'div');
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵsm(0,(null as any),$ctx$.myClassExp);
|
||||
$r3$.ɵsa(0);
|
||||
$r3$.ɵk(0,$r3$.ɵb($ctx$.myClassExp));
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -153,112 +150,5 @@ describe('compiler compliance: styling', () => {
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should place initial, multi, singular and application followed by attribute class instructions in the template code in that order',
|
||||
() => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`<div class="grape"
|
||||
[attr.class]="'banana'"
|
||||
[class.apple]="yesToApple"
|
||||
[class]="myClassExp"
|
||||
[class.orange]="yesToOrange"></div>\`
|
||||
})
|
||||
export class MyComponent {
|
||||
myClassExp = {a:true, b:true};
|
||||
yesToApple = true;
|
||||
yesToOrange = true;
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `
|
||||
const _c0 = ['grape','apple','orange',${InitialStylingFlags.VALUES_MODE},'grape',true];
|
||||
class MyComponent {
|
||||
static ngComponentDef = i0.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors:[['my-component']],
|
||||
factory:function MyComponent_Factory(){
|
||||
return new MyComponent();
|
||||
},
|
||||
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div');
|
||||
$r3$.ɵs((null as any), _c0);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵsm(0, (null as any), $ctx$.myClassExp);
|
||||
$r3$.ɵcp(0, 1, $ctx$.yesToApple);
|
||||
$r3$.ɵcp(0, 2, $ctx$.yesToOrange);
|
||||
$r3$.ɵsa(0);
|
||||
$r3$.ɵa(0, 'class', $r3$.ɵb('banana'));
|
||||
}
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should not generate the styling apply instruction if there are only static style/class attributes',
|
||||
() => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`<div class="foo"
|
||||
style="width:100px"
|
||||
[attr.class]="'round'"
|
||||
[attr.style]="'height:100px'"></div>\`
|
||||
})
|
||||
export class MyComponent {}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `
|
||||
const _c0 = ['width',${InitialStylingFlags.VALUES_MODE},'width','100px'];
|
||||
const _c1 = ['foo',${InitialStylingFlags.VALUES_MODE},'foo',true];
|
||||
class MyComponent {
|
||||
static ngComponentDef = i0.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors:[['my-component']],
|
||||
factory:function MyComponent_Factory(){
|
||||
return new MyComponent();
|
||||
},
|
||||
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div');
|
||||
$r3$.ɵs(_c0, _c1);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵa(0, 'class', $r3$.ɵb('round'));
|
||||
$r3$.ɵa(0, 'style', $r3$.ɵb('height:100px'));
|
||||
}
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -39,7 +39,6 @@ export {
|
||||
T as ɵT,
|
||||
V as ɵV,
|
||||
Q as ɵQ,
|
||||
Qr as ɵQr,
|
||||
d as ɵd,
|
||||
P as ɵP,
|
||||
b as ɵb,
|
||||
@ -70,7 +69,6 @@ export {
|
||||
cR as ɵcR,
|
||||
cr as ɵcr,
|
||||
qR as ɵqR,
|
||||
ql as ɵql,
|
||||
e as ɵe,
|
||||
p as ɵp,
|
||||
pD as ɵpD,
|
||||
@ -80,7 +78,8 @@ export {
|
||||
sm as ɵsm,
|
||||
sp as ɵsp,
|
||||
sa as ɵsa,
|
||||
cp as ɵcp,
|
||||
k as ɵk,
|
||||
kn as ɵkn,
|
||||
t as ɵt,
|
||||
v as ɵv,
|
||||
st as ɵst,
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
export * from './di/metadata';
|
||||
export {InjectableType, InjectorDef, InjectorType, defineInjectable, defineInjector} from './di/defs';
|
||||
export {InjectableType, InjectorType, defineInjectable, defineInjector} from './di/defs';
|
||||
export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref';
|
||||
export {Injectable, InjectableDecorator, InjectableProvider} from './di/injectable';
|
||||
export {inject, InjectFlags, INJECTOR, Injector} from './di/injector';
|
||||
|
@ -342,12 +342,9 @@ export interface Directive {
|
||||
* View queries are set before the `ngAfterViewInit` callback is called.
|
||||
*
|
||||
* @usageNotes
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* The following example shows how queries are defined
|
||||
* and when their results are available in lifecycle hooks:
|
||||
*
|
||||
* The followoing example (shows what??)
|
||||
* ```
|
||||
* @Component({
|
||||
* selector: 'someDir',
|
||||
@ -478,7 +475,7 @@ export interface Directive {
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of the Directive metadata.
|
||||
* Type of the Component metadata.
|
||||
*/
|
||||
export const Directive: DirectiveDecorator = makeDecorator(
|
||||
'Directive', (dir: Directive = {}) => dir, undefined, undefined,
|
||||
|
@ -19,9 +19,9 @@
|
||||
* The below symbols are used for @Injectable and @NgModule compilation.
|
||||
*/
|
||||
|
||||
export {InjectableDef, InjectorDef as ɵInjectorDef, defineInjectable, defineInjector} from './di/defs';
|
||||
export {InjectableDef, InjectorDef, defineInjectable, defineInjector} from './di/defs';
|
||||
export {inject} from './di/injector';
|
||||
export {NgModuleDef as ɵNgModuleDef} from './metadata/ng_module';
|
||||
export {NgModuleDef} from './metadata/ng_module';
|
||||
export {defineNgModule as ɵdefineNgModule} from './render3/definition';
|
||||
|
||||
|
||||
|
@ -63,7 +63,6 @@ export function assertComponentType(
|
||||
msg: string =
|
||||
'Type passed in is not ComponentType, it does not have \'ngComponentDef\' property.') {
|
||||
if (!actual.ngComponentDef) {
|
||||
debugger;
|
||||
throwError(msg);
|
||||
}
|
||||
}
|
||||
@ -71,4 +70,4 @@ export function assertComponentType(
|
||||
function throwError(msg: string): never {
|
||||
debugger; // Left intentionally for better debugger experience.
|
||||
throw new Error(`ASSERTION ERROR: ${msg}`);
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ export function defineComponent<T>(componentDefinition: {
|
||||
/**
|
||||
* Factory method used to create an instance of directive.
|
||||
*/
|
||||
factory: () => T;
|
||||
factory: () => T | ({0: T} & any[]); /* trying to say T | [T, ...any] */
|
||||
|
||||
/**
|
||||
* Static attributes to set on host element.
|
||||
@ -120,14 +120,6 @@ export function defineComponent<T>(componentDefinition: {
|
||||
*/
|
||||
hostBindings?: (directiveIndex: number, elementIndex: number) => void;
|
||||
|
||||
/**
|
||||
* Function to create instances of content queries associated with a given directive.
|
||||
*/
|
||||
contentQueries?: (() => void);
|
||||
|
||||
/** Refreshes content queries associated with directives in a given view */
|
||||
contentQueriesRefresh?: ((directiveIndex: number, queryIndex: number) => void);
|
||||
|
||||
/**
|
||||
* Defines the name that can be used in the template to assign this directive to a variable.
|
||||
*
|
||||
@ -224,8 +216,6 @@ export function defineComponent<T>(componentDefinition: {
|
||||
factory: componentDefinition.factory,
|
||||
template: componentDefinition.template || null !,
|
||||
hostBindings: componentDefinition.hostBindings || null,
|
||||
contentQueries: componentDefinition.contentQueries || null,
|
||||
contentQueriesRefresh: componentDefinition.contentQueriesRefresh || null,
|
||||
attributes: componentDefinition.attributes || null,
|
||||
inputs: invertObject(componentDefinition.inputs, declaredInputs),
|
||||
declaredInputs: declaredInputs,
|
||||
@ -458,14 +448,6 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
|
||||
*/
|
||||
hostBindings?: (directiveIndex: number, elementIndex: number) => void;
|
||||
|
||||
/**
|
||||
* Function to create instances of content queries associated with a given directive.
|
||||
*/
|
||||
contentQueries?: (() => void);
|
||||
|
||||
/** Refreshes content queries associated with directives in a given view */
|
||||
contentQueriesRefresh?: ((directiveIndex: number, queryIndex: number) => void);
|
||||
|
||||
/**
|
||||
* Defines the name that can be used in the template to assign this directive to a variable.
|
||||
*
|
||||
|
@ -19,7 +19,7 @@ import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_Vie
|
||||
import {Type} from '../type';
|
||||
|
||||
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
|
||||
import {addToViewTree, assertPreviousIsParent, createEmbeddedViewNode, createLContainer, createLNodeObject, createTNode, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
|
||||
import {addToViewTree, assertPreviousIsParent, createEmbeddedViewNode, createLContainer, createLNodeObject, createTNode, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
|
||||
import {VIEWS} from './interfaces/container';
|
||||
import {ComponentTemplate, DirectiveDefInternal, RenderFlags} from './interfaces/definition';
|
||||
import {LInjector} from './interfaces/injector';
|
||||
@ -378,7 +378,7 @@ export function getOrCreateInjectable<T>(
|
||||
// and matches the given token, return the directive instance.
|
||||
const directiveDef = defs[i] as DirectiveDefInternal<any>;
|
||||
if (directiveDef.type === token && directiveDef.diPublic) {
|
||||
return node.view[DIRECTIVES] ![i];
|
||||
return getDirectiveInstance(node.view[DIRECTIVES] ![i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,13 +51,14 @@ export {
|
||||
|
||||
element as Ee,
|
||||
elementAttribute as a,
|
||||
elementClassProp as cp,
|
||||
elementClass as k,
|
||||
elementClassNamed as kn,
|
||||
elementEnd as e,
|
||||
elementProperty as p,
|
||||
elementStart as E,
|
||||
|
||||
elementStyling as s,
|
||||
elementStylingMap as sm,
|
||||
elementStyle as sm,
|
||||
elementStyleProp as sp,
|
||||
elementStylingApply as sa,
|
||||
|
||||
@ -115,11 +116,6 @@ export {
|
||||
query as Q,
|
||||
queryRefresh as qR,
|
||||
} from './query';
|
||||
export {
|
||||
registerContentQuery as Qr,
|
||||
loadQueryList as ql,
|
||||
} from './instructions';
|
||||
|
||||
export {
|
||||
pureFunction0 as f0,
|
||||
pureFunction1 as f1,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user