Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
154289305e | |||
469b1e4a9a | |||
7fee1fd442 | |||
0ee5b7efa5 | |||
afff84c03f | |||
23f2a7069f | |||
42260702f7 | |||
eec231d21e | |||
95344d6039 | |||
1c9839e91d | |||
bc1a66e907 | |||
2a83dbb0d8 | |||
4007d00403 | |||
61e32ac3c4 | |||
43ee10fbbd | |||
eb90039ea1 | |||
5d318ff234 | |||
f3361abdd7 | |||
52cbe894e9 | |||
41c2030534 | |||
daee41a40a | |||
68bd45ba87 | |||
0f6407750b | |||
95fca24fd8 |
1
.github/angular-robot.yml
vendored
@ -4,6 +4,7 @@
|
||||
size:
|
||||
disabled: false
|
||||
maxSizeIncrease: 1000
|
||||
circleCiStatusName: "ci/circleci: build-packages-dist"
|
||||
status:
|
||||
disabled: false
|
||||
context: "ci/angular: size"
|
||||
|
10
CHANGELOG.md
@ -1,3 +1,13 @@
|
||||
<a name="6.0.3"></a>
|
||||
## [6.0.3](https://github.com/angular/angular/compare/6.0.2...6.0.3) (2018-05-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0ee5b7e](https://github.com/angular/angular/commit/0ee5b7e))
|
||||
|
||||
|
||||
|
||||
<a name="6.0.2"></a>
|
||||
## [6.0.2](https://github.com/angular/angular/compare/6.0.1...6.0.2) (2018-05-15)
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
# MasterProject
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0-rc.0.
|
||||
|
||||
## Development server
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
Before running the tests make sure you are serving the app via `ng serve`.
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
@ -5,18 +5,18 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
selector: 'app-voter',
|
||||
template: `
|
||||
<h4>{{name}}</h4>
|
||||
<button (click)="vote(true)" [disabled]="voted">Agree</button>
|
||||
<button (click)="vote(false)" [disabled]="voted">Disagree</button>
|
||||
<button (click)="vote(true)" [disabled]="didVote">Agree</button>
|
||||
<button (click)="vote(false)" [disabled]="didVote">Disagree</button>
|
||||
`
|
||||
})
|
||||
export class VoterComponent {
|
||||
@Input() name: string;
|
||||
@Output() onVoted = new EventEmitter<boolean>();
|
||||
voted = false;
|
||||
@Output() voted = new EventEmitter<boolean>();
|
||||
didVote = false;
|
||||
|
||||
vote(agreed: boolean) {
|
||||
this.onVoted.emit(agreed);
|
||||
this.voted = true;
|
||||
this.voted.emit(agreed);
|
||||
this.didVote = true;
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
||||
|
@ -8,7 +8,7 @@ import { Component } from '@angular/core';
|
||||
<h3>Agree: {{agreed}}, Disagree: {{disagreed}}</h3>
|
||||
<app-voter *ngFor="let voter of voters"
|
||||
[name]="voter"
|
||||
(onVoted)="onVoted($event)">
|
||||
(voted)="onVoted($event)">
|
||||
</app-voter>
|
||||
`
|
||||
})
|
||||
|
@ -1,26 +1,26 @@
|
||||
// Import spec files individually for Stackblitz
|
||||
import 'app/about/about.component.spec.ts';
|
||||
import 'app/app-initial.component.spec.ts';
|
||||
import 'app/app.component.router.spec.ts';
|
||||
import 'app/app.component.spec.ts';
|
||||
import 'app/banner/banner-initial.component.spec.ts';
|
||||
import 'app/banner/banner.component.spec.ts';
|
||||
import 'app/banner/banner.component.detect-changes.spec.ts';
|
||||
import 'app/banner/banner-external.component.spec.ts';
|
||||
import 'app/dashboard/dashboard-hero.component.spec.ts';
|
||||
import 'app/dashboard/dashboard.component.no-testbed.spec.ts';
|
||||
import 'app/dashboard/dashboard.component.spec.ts';
|
||||
import 'app/demo/async-helper.spec.ts';
|
||||
import 'app/demo/demo.spec.ts';
|
||||
import 'app/demo/demo.testbed.spec.ts';
|
||||
import 'app/hero/hero-detail.component.no-testbed.spec.ts';
|
||||
import 'app/hero/hero-detail.component.spec.ts';
|
||||
import 'app/hero/hero-list.component.spec.ts';
|
||||
import 'app/model/hero.service.spec.ts';
|
||||
import 'app/model/http-hero.service.spec.ts';
|
||||
import 'app/model/testing/http-client.spec.ts';
|
||||
import 'app/shared/highlight.directive.spec.ts';
|
||||
import 'app/shared/title-case.pipe.spec.ts';
|
||||
import 'app/twain/twain.component.spec.ts';
|
||||
import 'app/twain/twain.component.marbles.spec.ts';
|
||||
import 'app/welcome/welcome.component.spec.ts';
|
||||
import './app/about/about.component.spec.ts';
|
||||
import './app/app-initial.component.spec.ts';
|
||||
import './app/app.component.router.spec.ts';
|
||||
import './app/app.component.spec.ts';
|
||||
import './app/banner/banner-initial.component.spec.ts';
|
||||
import './app/banner/banner.component.spec.ts';
|
||||
import './app/banner/banner.component.detect-changes.spec.ts';
|
||||
import './app/banner/banner-external.component.spec.ts';
|
||||
import './app/dashboard/dashboard-hero.component.spec.ts';
|
||||
import './app/dashboard/dashboard.component.no-testbed.spec.ts';
|
||||
import './app/dashboard/dashboard.component.spec.ts';
|
||||
import './app/demo/async-helper.spec.ts';
|
||||
import './app/demo/demo.spec.ts';
|
||||
import './app/demo/demo.testbed.spec.ts';
|
||||
import './app/hero/hero-detail.component.no-testbed.spec.ts';
|
||||
import './app/hero/hero-detail.component.spec.ts';
|
||||
import './app/hero/hero-list.component.spec.ts';
|
||||
import './app/model/hero.service.spec.ts';
|
||||
import './app/model/http-hero.service.spec.ts';
|
||||
import './app/model/testing/http-client.spec.ts';
|
||||
import './app/shared/highlight.directive.spec.ts';
|
||||
import './app/shared/title-case.pipe.spec.ts';
|
||||
import './app/twain/twain.component.spec.ts';
|
||||
import './app/twain/twain.component.marbles.spec.ts';
|
||||
import './app/welcome/welcome.component.spec.ts';
|
||||
|
@ -439,7 +439,7 @@ Observables can deliver single or multiple values of any type to subscribers, ei
|
||||
|
||||
Angular uses a third-party library called [Reactive Extensions (RxJS)](http://reactivex.io/rxjs/).
|
||||
|
||||
To learn more, see the [Observables](guide/glossary#observable) guide.
|
||||
To learn more, see the [Observables](guide/observables) guide.
|
||||
|
||||
|
||||
{@a observer}
|
||||
|
@ -1034,7 +1034,7 @@ Call `request.flush()` with an error message, as seen in the following example.
|
||||
|
||||
<code-example
|
||||
path="http/src/testing/http-client.spec.ts"
|
||||
region="404"
|
||||
region="network-error"
|
||||
linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
@ -129,6 +129,6 @@ Any changes to the public API surface will be done using the versioning, support
|
||||
|
||||
Angular Labs is an initiative to cultivate new features and iterate on them quickly. Angular Labs provides a safe place for exploration and experimentation by the Angular team.
|
||||
|
||||
Angular Labs projects are are not ready for production use, and no commitment is made to bring them to production. The policies and practices that are described in this document do not apply to Angular Labs projects.
|
||||
Angular Labs projects are not ready for production use, and no commitment is made to bring them to production. The policies and practices that are described in this document do not apply to Angular Labs projects.
|
||||
|
||||
Angular Labs projects typically are in separate branches in the Angular repo, clearly separated from the main Angular codebase.
|
||||
|
@ -3656,7 +3656,7 @@ Lazy loading has multiple benefits.
|
||||
* You can speed up load time for users that only visit certain areas of the application.
|
||||
* You can continue expanding lazy loaded feature areas without increasing the size of the initial load bundle.
|
||||
|
||||
You're already made part way there.
|
||||
You're already part of the way there.
|
||||
By organizing the application into modules—`AppModule`,
|
||||
`HeroesModule`, `AdminModule` and `CrisisCenterModule`—you
|
||||
have natural candidates for lazy loading.
|
||||
|
@ -180,7 +180,7 @@ npm install --save @angular/platform-server @nguniversal/module-map-ngfactory-lo
|
||||
|
||||
{@a transition}
|
||||
|
||||
### Modify the client app
|
||||
## Modify the client app
|
||||
|
||||
A Universal app can act as a dynamic, content-rich "splash screen" that engages the user.
|
||||
It gives the appearance of a near-instant application.
|
||||
@ -190,7 +190,9 @@ Once loaded, Angular transitions from the static server-rendered page to the dyn
|
||||
|
||||
You must make a few changes to your application code to support both server-side rendering and the transition to the client app.
|
||||
|
||||
#### The root `AppModule`
|
||||
{@a root-app-module}
|
||||
|
||||
### The root `AppModule`
|
||||
|
||||
Open file `src/app/app.module.ts` and find the `BrowserModule` import in the `NgModule` metadata.
|
||||
Replace that import with this one:
|
||||
@ -206,9 +208,29 @@ You can get runtime information about the current platform and the `appId` by in
|
||||
<code-example path="universal/src/app/app.module.ts" region="platform-detection" title="src/app/app.module.ts (platform detection)">
|
||||
</code-example>
|
||||
|
||||
{@a cli-output}
|
||||
|
||||
### Build Destination
|
||||
|
||||
A Universal app is distributed in two parts: the server-side code that serves up the initial application, and the client-side code that's loaded in dynamically.
|
||||
|
||||
The Angular CLI outputs the client-side code in the `dist` directory by default, so you modify the `outputPath` for the __build__ target in the `angular.json` to keep the client-side build outputs separate from the server-side code. The client-side build output will be served by the Express server.
|
||||
|
||||
```
|
||||
...
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/browser",
|
||||
...
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
{@a http-urls}
|
||||
|
||||
#### Absolute HTTP URLs
|
||||
### Absolute HTTP URLs
|
||||
|
||||
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data.
|
||||
These services send requests to _relative_ URLs such as `api/heroes`.
|
||||
@ -262,6 +284,19 @@ The `ModuleMapLoaderModule` is a server-side module that allows lazy-loading of
|
||||
|
||||
This is also the place to register providers that are specific to running your app under Universal.
|
||||
|
||||
{@a app-server-entry-point}
|
||||
|
||||
### App server entry point
|
||||
|
||||
The `Angular CLI` uses the `AppServerModule` to build the server-side bundle.
|
||||
|
||||
Create a `main.server.ts` file in the `src/` directory that exports the `AppServerModule`:
|
||||
|
||||
<code-example path="universal/src/main.server.ts" title="src/main.server.ts">
|
||||
</code-example>
|
||||
|
||||
The `main.server.ts` will be referenced later to add a `server` target to the `Angular CLI` configuration.
|
||||
|
||||
{@a web-server}
|
||||
|
||||
### Universal web server
|
||||
@ -421,6 +456,8 @@ This config extends from the root's `tsconfig.json` file. Certain settings are n
|
||||
* The `angularCompilerOptions` section guides the AOT compiler:
|
||||
* `entryModule` - the root module of the server application, expressed as `path/to/file#ClassName`.
|
||||
|
||||
{@a universal-webpack-configuration}
|
||||
|
||||
### Universal Webpack configuration
|
||||
|
||||
Universal applications doesn't need any extra Webpack configuration, the CLI takes care of that for you,
|
||||
@ -433,13 +470,38 @@ Create a `webpack.server.config.js` file in the project root directory with the
|
||||
|
||||
**Webpack configuration** is a rich topic beyond the scope of this guide.
|
||||
|
||||
{@a universal-cli-configuration}
|
||||
|
||||
### Angular CLI configuration
|
||||
|
||||
The CLI provides builders for different types of __targets__. Commonly known targets such as `build` and `serve` already exist in the `angular.json` configuration. To target a server-side build, add a `server` target to the `architect` configuration object.
|
||||
|
||||
* The `outputPath` tells where the resulting build will be created.
|
||||
* The `main` provides the main entry point to the previously created `main.server.ts`
|
||||
* The `tsConfig` uses the `tsconfig.server.json` as configuration for the TypeScript and AOT compilation.
|
||||
|
||||
```
|
||||
"architect": {
|
||||
...
|
||||
"server": {
|
||||
"builder": "@angular-devkit/build-angular:server",
|
||||
"options": {
|
||||
"outputPath": "dist/server",
|
||||
"main": "src/main.server.ts",
|
||||
"tsConfig": "src/tsconfig.server.json"
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Build and run with universal
|
||||
|
||||
Now that you've created the TypeScript and Webpack config files, you can build and run the Universal application.
|
||||
Now that you've created the TypeScript and Webpack config files and configured the Angular CLI, you can build and run the Universal application.
|
||||
|
||||
First add the _build_ and _serve_ commands to the `scripts` section of the `package.json`:
|
||||
|
||||
<code-example format="." language="ts">
|
||||
```
|
||||
"scripts": {
|
||||
...
|
||||
"build:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
|
||||
@ -448,7 +510,7 @@ First add the _build_ and _serve_ commands to the `scripts` section of the `pack
|
||||
"webpack:server": "webpack --config webpack.server.config.js --progress --colors"
|
||||
...
|
||||
}
|
||||
</code-example>
|
||||
```
|
||||
|
||||
{@a build}
|
||||
|
||||
|
BIN
aio/content/images/bios/mhartington.png
Normal file
After Width: | Height: | Size: 28 KiB |
@ -592,7 +592,7 @@
|
||||
"bio": "Nir is a Principal Frontend Consultant & Head of the Angular department at 500Tech, Google Developer Expert and community leader. He organizes the largest Angular meetup group in Israel (Angular-IL), talks and teaches about front-end technologies around the world. He is also the author of two books about Angular and the founder of the 'Frontend Band'.",
|
||||
"group": "GDE"
|
||||
},
|
||||
|
||||
|
||||
"achautard": {
|
||||
"name": "Alain Chautard",
|
||||
"picture": "alainchautard.png",
|
||||
@ -609,5 +609,14 @@
|
||||
"website": "https://coryrylan.com",
|
||||
"bio": "Cory is a full time front end web developer. He works full time building responsive web applications and progressive web apps. When not building web apps he is busy teaching Angular and other web technologies in workshops and conferences. He loves the web and is optimistic of the places it can take us.",
|
||||
"group": "GDE"
|
||||
},
|
||||
|
||||
"mhartington": {
|
||||
"name": "Mike Hartington",
|
||||
"picture": "mhartington.png",
|
||||
"twitter": "mhartington",
|
||||
"website": "https://mhartington.io",
|
||||
"bio": "Mike is a Developer Advocate for the Ionic Framework and a GDE in Angular. He spends most of his time making fast PWAs and exploring emerging web standards. When not behind a keyboard, you'll probably find him with a guitar and beer.",
|
||||
"group": "GDE"
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,12 @@
|
||||
<td>Tokyo, Japan</td>
|
||||
<td>Jun 16, 2018</td>
|
||||
</tr>
|
||||
<!-- Angular Conf Australia-->
|
||||
<tr>
|
||||
<th><a href="https://www.angularconf.com.au/" title="Angular Conf Australia">Angular Conf Australia</a></th>
|
||||
<td>Melbourne, Australia</td>
|
||||
<td>Jun 22, 2018</td>
|
||||
</tr>
|
||||
<!-- AngularConnect-->
|
||||
<tr>
|
||||
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
|
||||
|
@ -78,6 +78,440 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div>
|
||||
<h2>BRAND ICONS</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/animations.png" alt="Animations Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">ANIMATIONS</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Animations Icon (png) - <a href="assets/images/logos/concept-icons/animations.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Animations Icon (svg) - <a href="assets/images/logos/concept-icons/animations.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/augury.png" alt="Augury Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">AUGURY</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Augury Icon (png) - <a href="assets/images/logos/concept-icons/augury.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Augury Icon (svg) - <a href="assets/images/logos/concept-icons/augury.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/cdk.png" alt="CDK Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">COMPONENT DEV KIT (CDK)</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>CDK Icon (png) - <a href="assets/images/logos/concept-icons/cdk.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>CDK Icon (svg) - <a href="assets/images/logos/concept-icons/cdk.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/cli.png" alt="CLI Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">CLI</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>CLI Icon (png) - <a href="assets/images/logos/concept-icons/cli.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>CLI Icon (svg) - <a href="assets/images/logos/concept-icons/cli.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/compiler.png" alt="Compiler Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">COMPILER</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Compiler Icon (png) - <a href="assets/images/logos/concept-icons/compiler.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Compiler Icon (svg) - <a href="assets/images/logos/concept-icons/compiler.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/components.png" alt="Components Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">WEB COMPONENTS</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Web Components Icon (png) - <a href="assets/images/logos/concept-icons/components.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Web Components Icon (svg) - <a href="assets/images/logos/concept-icons/components.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/forms.png" alt="Forms Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">FORMS</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Forms Icon (png) - <a href="assets/images/logos/concept-icons/forms.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Forms Icon (svg) - <a href="assets/images/logos/concept-icons/forms.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/http.png" alt="HTTP Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">HTTP</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>HTTP Icon (png) - <a href="assets/images/logos/concept-icons/http.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>HTTP Icon (svg) - <a href="assets/images/logos/concept-icons/http.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/i18n.png" alt="i18n Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">i18n</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>HTTP Icon (png) - <a href="assets/images/logos/concept-icons/i18n.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>HTTP Icon (svg) - <a href="assets/images/logos/concept-icons/i18n.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/karma.png" alt="Karma Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">KARMA</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Karma Icon (png) - <a href="assets/images/logos/concept-icons/karma.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Karma Icon (svg) - <a href="assets/images/logos/concept-icons/karma.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/labs.png" alt="Labs Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">LABS</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Labs Icon (png) - <a href="assets/images/logos/concept-icons/labs.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Labs Icon (svg) - <a href="assets/images/logos/concept-icons/labs.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/language-services.png" alt="Language Services Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">LANGUAGE SERVICES</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Language Services Icon (png) - <a href="assets/images/logos/concept-icons/language-services.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Language Services Icon (svg) - <a href="assets/images/logos/concept-icons/language-services.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/material.png" alt="Material Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">MATERIAL</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Material Icon (png) - <a href="assets/images/logos/concept-icons/material.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Material Icon (svg) - <a href="assets/images/logos/concept-icons/material.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/protractor.png" alt="Protractor Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">PROTRACTOR</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Protractor Icon (png) - <a href="assets/images/logos/concept-icons/protractor.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Protractor Icon (svg) - <a href="assets/images/logos/concept-icons/protractor.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/pwa.png" alt="PWA Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">PWA</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>PWA Icon (png) - <a href="assets/images/logos/concept-icons/pwa.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>PWA Icon (svg) - <a href="assets/images/logos/concept-icons/pwa.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/router.png" alt="Router Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">ROUTER</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Router Icon (png) - <a href="assets/images/logos/concept-icons/router.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Router Icon (svg) - <a href="assets/images/logos/concept-icons/router.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/universal.png" alt="Universal Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">UNIVERSAL</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Universal Icon (png) - <a href="assets/images/logos/concept-icons/universal.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Universal Icon (svg) - <a href="assets/images/logos/concept-icons/universal.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div>
|
||||
<h2>CONCEPT & FEATURE ICONS</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/dependency-injection.png" alt="Dependency Injection Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">DEPENDENCY INJECTION</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Dependency Injection Icon (png) - <a href="assets/images/logos/concept-icons/dependency-injection.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Dependency Injection Icon (svg) - <a href="assets/images/logos/concept-icons/dependency-injection.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/lazy-loading.png" alt="Lazy Loading Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">LAZY LOADING</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Lazy Loading Icon (png) - <a href="assets/images/logos/concept-icons/lazy-loading.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Lazy Loading Icon (svg) - <a href="assets/images/logos/concept-icons/lazy-loading.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/libraries.png" alt="Libraries Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">LIBRARIES</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Libraries Icon (png) - <a href="assets/images/logos/concept-icons/libraries.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Libraries Icon (svg) - <a href="assets/images/logos/concept-icons/libraries.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/performance.png" alt="Performance Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">PERFORMANCE</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Performance Icon (png) - <a href="assets/images/logos/concept-icons/performance.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Performance Icon (svg) - <a href="assets/images/logos/concept-icons/performance.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div class="presskit-image-container">
|
||||
<img src="assets/images/logos/concept-icons/templates.png" alt="Templates Icon">
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="l-space-left-3">TEMPLATES</h3>
|
||||
<ul class="l-space-left-3">
|
||||
<li>
|
||||
<span>Templates Icon (png) - <a href="assets/images/logos/concept-icons/templates.png" download>Download</a></span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Templates Icon (svg) - <a href="assets/images/logos/concept-icons/templates.svg" download>Download</a></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="presskit-row">
|
||||
<div class="presskit-inner">
|
||||
<div>
|
||||
|
@ -345,6 +345,12 @@
|
||||
"title": "Angular Material",
|
||||
"url": "https://github.com/angular/material2"
|
||||
},
|
||||
"ngzorro": {
|
||||
"desc": "A set of enterprise-class UI components based on Ant Design and Angular",
|
||||
"rev": true,
|
||||
"title": "Ant Design of Angular (ng-zorro-antd)",
|
||||
"url": "https://ng.ant.design/docs/introduce/en"
|
||||
},
|
||||
"aggrid": {
|
||||
"desc": "A datagrid for Angular with enterprise style features such as sorting, filtering, custom rendering, editing, grouping, aggregation and pivoting.",
|
||||
"rev": true,
|
||||
@ -597,12 +603,6 @@
|
||||
"Workshops & Onsite Training": {
|
||||
"order": 2,
|
||||
"resources": {
|
||||
"-KLIBo3ANF3-1B9wxsoB": {
|
||||
"desc": "Angular Classes from Intertech in Minnesota",
|
||||
"rev": true,
|
||||
"title": "Intertech",
|
||||
"url": "http://www.intertech.com/Training/Web-Dev/AngularJS/AngularJS/Angular-2-Training"
|
||||
},
|
||||
"-KLIBoFWStce29UCwkvY": {
|
||||
"desc": "Private Angular Training and Mentoring",
|
||||
"rev": true,
|
||||
|
@ -1,5 +1,7 @@
|
||||
<!-- Content projection is used to get the content HTML provided to the component. -->
|
||||
<span #content style="display: none"><ng-content></ng-content></span>
|
||||
|
||||
<span [ngSwitch]="mode">
|
||||
<span *ngSwitchCase="'disabled'">{{title}} <em>(not available on this device)</em></span>
|
||||
<span *ngSwitchCase="'embedded'">
|
||||
<div title="{{title}}">
|
||||
<aio-embedded-stackblitz [src]="stackblitz"></aio-embedded-stackblitz>
|
||||
@ -14,7 +16,7 @@
|
||||
<span *ngSwitchDefault>
|
||||
<a [href]="stackblitz" target="_blank" title="{{title}}">{{title}}</a>
|
||||
<span *ngIf="enableDownload">
|
||||
/ <a [href]="zip" download title="Download example">download example</a>
|
||||
/ <a [href]="zip" download title="Download example">download example</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -12,7 +12,6 @@ describe('LiveExampleComponent', () => {
|
||||
let liveExampleComponent: LiveExampleComponent;
|
||||
let fixture: ComponentFixture<HostComponent>;
|
||||
let testPath: string;
|
||||
let liveExampleContent: string|null;
|
||||
|
||||
//////// test helpers ////////
|
||||
|
||||
@ -41,12 +40,7 @@ describe('LiveExampleComponent', () => {
|
||||
liveExampleDe = fixture.debugElement.children[0];
|
||||
liveExampleComponent = liveExampleDe.componentInstance;
|
||||
|
||||
// Copy the LiveExample's innerHTML (content)
|
||||
// into the `liveExampleContent` property as the DocViewer does
|
||||
liveExampleDe.nativeElement.liveExampleContent = liveExampleContent;
|
||||
|
||||
fixture.detectChanges();
|
||||
liveExampleComponent.onResize(1033); // wide by default
|
||||
// Trigger `ngAfterContentInit()`.
|
||||
fixture.detectChanges();
|
||||
|
||||
testFn();
|
||||
@ -64,7 +58,6 @@ describe('LiveExampleComponent', () => {
|
||||
.overrideComponent(EmbeddedStackblitzComponent, {set: {template: 'NO IFRAME'}});
|
||||
|
||||
testPath = defaultTestPath;
|
||||
liveExampleContent = null;
|
||||
});
|
||||
|
||||
describe('when not embedded', () => {
|
||||
@ -103,15 +96,6 @@ describe('LiveExampleComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should have expected flat-style stackblitz when has `flat-style`', () => {
|
||||
testPath = '/tutorial/toh-pt1';
|
||||
setHostTemplate('<live-example flat-style></live-example>');
|
||||
testComponent(() => {
|
||||
// The file should be "stackblitz.html", not "stackblitz.html"
|
||||
expect(getLiveExampleAnchor().href).toContain('/stackblitz.html');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have expected stackblitz & download hrefs when has example directory (name)', () => {
|
||||
testPath = '/guide/somewhere';
|
||||
setHostTemplate('<live-example name="toh-pt1"></live-example>');
|
||||
@ -150,15 +134,7 @@ describe('LiveExampleComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be flat style when flat-style requested', () => {
|
||||
setHostTemplate('<live-example flat-style></live-example>');
|
||||
testComponent(() => {
|
||||
const hrefs = getHrefs();
|
||||
expect(hrefs[0]).toContain(defaultTestPath + '/stackblitz.html');
|
||||
});
|
||||
});
|
||||
|
||||
it('should not have a download link when `noDownload` atty present', () => {
|
||||
it('should not have a download link when `noDownload` attr present', () => {
|
||||
setHostTemplate('<live-example noDownload></live-example>');
|
||||
testComponent(() => {
|
||||
const hrefs = getHrefs();
|
||||
@ -167,7 +143,7 @@ describe('LiveExampleComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should only have a download link when `downloadOnly` atty present', () => {
|
||||
it('should only have a download link when `downloadOnly` attr present', () => {
|
||||
setHostTemplate('<live-example downloadOnly>download this</live-example>');
|
||||
testComponent(() => {
|
||||
const hrefs = getHrefs();
|
||||
@ -196,12 +172,12 @@ describe('LiveExampleComponent', () => {
|
||||
});
|
||||
|
||||
it('should add title from <live-example> body', () => {
|
||||
liveExampleContent = 'The Greatest Example';
|
||||
setHostTemplate('<live-example title="ignore this title"></live-example>');
|
||||
const expectedTitle = 'The Greatest Example';
|
||||
setHostTemplate(`<live-example title="ignore this title">${expectedTitle}</live-example>`);
|
||||
testComponent(() => {
|
||||
const anchor = getLiveExampleAnchor();
|
||||
expect(anchor.textContent).toBe(liveExampleContent, 'anchor content');
|
||||
expect(anchor.getAttribute('title')).toBe(liveExampleContent, 'title');
|
||||
expect(anchor.textContent).toBe(expectedTitle, 'anchor content');
|
||||
expect(anchor.getAttribute('title')).toBe(expectedTitle, 'title');
|
||||
});
|
||||
});
|
||||
|
||||
@ -251,27 +227,4 @@ describe('LiveExampleComponent', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when narrow display (mobile)', () => {
|
||||
|
||||
it('should be embedded style when no style defined', () => {
|
||||
setHostTemplate('<live-example></live-example>');
|
||||
testComponent(() => {
|
||||
liveExampleComponent.onResize(600); // narrow
|
||||
fixture.detectChanges();
|
||||
const hrefs = getHrefs();
|
||||
expect(hrefs[0]).toContain(defaultTestPath + '/stackblitz.html');
|
||||
});
|
||||
});
|
||||
|
||||
it('should be embedded style even when flat-style requested', () => {
|
||||
setHostTemplate('<live-example flat-style></live-example>');
|
||||
testComponent(() => {
|
||||
liveExampleComponent.onResize(600); // narrow
|
||||
fixture.detectChanges();
|
||||
const hrefs = getHrefs();
|
||||
expect(hrefs[0]).toContain(defaultTestPath + '/stackblitz.html');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,130 +1,131 @@
|
||||
/* tslint:disable component-selector */
|
||||
import { Component, ElementRef, HostListener, Input, OnInit, AfterViewInit, ViewChild } from '@angular/core';
|
||||
import { AfterContentInit, AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { CONTENT_URL_PREFIX } from 'app/documents/document.service';
|
||||
import { AttrMap, boolFromValue, getAttrs, getAttrValue } from 'app/shared/attribute-utils';
|
||||
|
||||
import { boolFromValue, getAttrs, getAttrValue } from 'app/shared/attribute-utils';
|
||||
|
||||
const liveExampleBase = CONTENT_URL_PREFIX + 'live-examples/';
|
||||
const zipBase = CONTENT_URL_PREFIX + 'zips/';
|
||||
const LIVE_EXAMPLE_BASE = CONTENT_URL_PREFIX + 'live-examples/';
|
||||
const ZIP_BASE = CONTENT_URL_PREFIX + 'zips/';
|
||||
|
||||
/**
|
||||
* Angular.io Live Example Embedded Component
|
||||
*
|
||||
* Renders a link to a live/host example of the doc page.
|
||||
*
|
||||
* All attributes and the text content are optional
|
||||
*
|
||||
* Usage:
|
||||
* <live-example
|
||||
* [name="..."] // name of the example directory
|
||||
* [stackblitz="...""] // name of the stackblitz file (becomes part of zip file name as well)
|
||||
* [embedded] // embed the stackblitz in the doc page, else display in new browser tab (default)
|
||||
* [noDownload] // no downloadable zip option
|
||||
* [downloadOnly] // just the zip
|
||||
* [title="..."]> // text for live example link and tooltip
|
||||
* text // higher precedence way to specify text for live example link and tooltip
|
||||
* </live-example>
|
||||
* Example:
|
||||
* <p>Run <live-example>Try the live example</live-example></p>.
|
||||
* // ~/resources/live-examples/{page}/stackblitz.json
|
||||
*
|
||||
* <p>Run <live-example name="toh-pt1">this example</live-example></p>.
|
||||
* // ~/resources/live-examples/toh-pt1/stackblitz.json
|
||||
*
|
||||
* // Link to the default stackblitz in the toh-pt1 sample
|
||||
* // The title overrides default ("live example") with "Tour of Heroes - Part 1"
|
||||
* <p>Run <live-example name="toh-pt1" title="Tour of Heroes - Part 1"></live-example></p>.
|
||||
* // ~/resources/live-examples/toh-pt1/stackblitz.json
|
||||
*
|
||||
* <p>Run <live-example stackblitz="minimal"></live-example></p>.
|
||||
* // ~/resources/live-examples/{page}/minimal.stackblitz.json
|
||||
*
|
||||
* // Embed the current page's default stackblitz
|
||||
* // Text within tag is "live example"
|
||||
* // No title (no tooltip)
|
||||
* <live-example embedded title=""></live-example>
|
||||
* // ~/resources/live-examples/{page}/stackblitz.json
|
||||
*
|
||||
* // Displays within the document page as an embedded style stackblitz editor
|
||||
* <live-example name="toh-pt1" embedded stackblitz="minimal">Tour of Heroes - Part 1</live-example>
|
||||
* // ~/resources/live-examples/toh-pt1/minimal.stackblitz.json
|
||||
*/
|
||||
* Angular.io Live Example Embedded Component
|
||||
*
|
||||
* Renders a link to a live/host example of the doc page.
|
||||
*
|
||||
* All attributes and the text content are optional
|
||||
*
|
||||
* Usage:
|
||||
* <live-example
|
||||
* [name="..."] // name of the example directory
|
||||
* [stackblitz="...""] // name of the stackblitz file (becomes part of zip file name as well)
|
||||
* [embedded] // embed the stackblitz in the doc page, else display in new browser tab (default)
|
||||
* [noDownload] // no downloadable zip option
|
||||
* [downloadOnly] // just the zip
|
||||
* [title="..."]> // text for live example link and tooltip
|
||||
* text // higher precedence way to specify text for live example link and tooltip
|
||||
* </live-example>
|
||||
* Example:
|
||||
* <p>Run <live-example>Try the live example</live-example></p>.
|
||||
* // ~/resources/live-examples/{page}/stackblitz.json
|
||||
*
|
||||
* <p>Run <live-example name="toh-pt1">this example</live-example></p>.
|
||||
* // ~/resources/live-examples/toh-pt1/stackblitz.json
|
||||
*
|
||||
* // Link to the default stackblitz in the toh-pt1 sample
|
||||
* // The title overrides default ("live example") with "Tour of Heroes - Part 1"
|
||||
* <p>Run <live-example name="toh-pt1" title="Tour of Heroes - Part 1"></live-example></p>.
|
||||
* // ~/resources/live-examples/toh-pt1/stackblitz.json
|
||||
*
|
||||
* <p>Run <live-example stackblitz="minimal"></live-example></p>.
|
||||
* // ~/resources/live-examples/{page}/minimal.stackblitz.json
|
||||
*
|
||||
* // Embed the current page's default stackblitz
|
||||
* // Text within tag is "live example"
|
||||
* // No title (no tooltip)
|
||||
* <live-example embedded title=""></live-example>
|
||||
* // ~/resources/live-examples/{page}/stackblitz.json
|
||||
*
|
||||
* // Displays within the document page as an embedded style stackblitz editor
|
||||
* <live-example name="toh-pt1" embedded stackblitz="minimal">Tour of Heroes - Part 1</live-example>
|
||||
* // ~/resources/live-examples/toh-pt1/minimal.stackblitz.json
|
||||
*/
|
||||
@Component({
|
||||
selector: 'live-example',
|
||||
templateUrl: 'live-example.component.html'
|
||||
})
|
||||
export class LiveExampleComponent implements OnInit {
|
||||
export class LiveExampleComponent implements AfterContentInit {
|
||||
|
||||
// Will force to embedded-style when viewport width is narrow
|
||||
// "narrow" value was picked based on phone dimensions from http://screensiz.es/phone
|
||||
readonly narrowWidth = 1000;
|
||||
|
||||
attrs: any;
|
||||
enableDownload = true;
|
||||
exampleDir: string;
|
||||
isEmbedded = false;
|
||||
mode = 'disabled';
|
||||
stackblitz: string;
|
||||
stackblitzName: string;
|
||||
readonly mode: 'default' | 'embedded' | 'downloadOnly';
|
||||
readonly enableDownload: boolean;
|
||||
readonly stackblitz: string;
|
||||
readonly zip: string;
|
||||
title: string;
|
||||
zip: string;
|
||||
zipName: string;
|
||||
|
||||
constructor(
|
||||
private elementRef: ElementRef,
|
||||
location: Location ) {
|
||||
@ViewChild('content')
|
||||
private content: ElementRef;
|
||||
|
||||
const attrs = this.attrs = getAttrs(this.elementRef);
|
||||
let exampleDir = attrs.name;
|
||||
constructor(elementRef: ElementRef, location: Location) {
|
||||
const attrs = getAttrs(elementRef);
|
||||
const exampleDir = this.getExampleDir(attrs, location.path(false));
|
||||
const stackblitzName = this.getStackblitzName(attrs);
|
||||
|
||||
this.mode = this.getMode(attrs);
|
||||
this.enableDownload = this.getEnableDownload(attrs);
|
||||
this.stackblitz = this.getStackblitz(exampleDir, stackblitzName, this.mode === 'embedded');
|
||||
this.zip = this.getZip(exampleDir, stackblitzName);
|
||||
this.title = this.getTitle(attrs);
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
// Angular will sanitize this title when displayed, so it should be plain text.
|
||||
const textContent = this.content.nativeElement.textContent.trim();
|
||||
if (textContent) {
|
||||
this.title = textContent;
|
||||
}
|
||||
}
|
||||
|
||||
private getEnableDownload(attrs: AttrMap) {
|
||||
const downloadDisabled = boolFromValue(getAttrValue(attrs, 'noDownload'));
|
||||
return !downloadDisabled;
|
||||
}
|
||||
|
||||
private getExampleDir(attrs: AttrMap, path: string) {
|
||||
let exampleDir = getAttrValue(attrs, 'name');
|
||||
if (!exampleDir) {
|
||||
// take last segment, excluding hash fragment and query params
|
||||
exampleDir = (location.path(false).match(/[^\/?\#]+(?=\/?(?:$|\#|\?))/) || [])[0];
|
||||
}
|
||||
this.exampleDir = exampleDir.trim();
|
||||
this.zipName = exampleDir.indexOf('/') === -1 ? this.exampleDir : exampleDir.split('/')[0];
|
||||
this.stackblitzName = attrs.stackblitz ? attrs.stackblitz.trim() + '.' : '';
|
||||
this.zip = `${zipBase}${exampleDir}/${this.stackblitzName}${this.zipName}.zip`;
|
||||
|
||||
this.enableDownload = !boolFromValue(getAttrValue(attrs, 'nodownload'));
|
||||
|
||||
if (boolFromValue(getAttrValue(attrs, 'downloadonly'))) {
|
||||
this.mode = 'downloadOnly';
|
||||
// Take the last path segment, excluding query params and hash fragment.
|
||||
const match = path.match(/[^/?#]+(?=\/?(?:\?|#|$))/);
|
||||
exampleDir = match ? match[0] : 'index';
|
||||
}
|
||||
return exampleDir.trim();
|
||||
}
|
||||
|
||||
calcStackblitzLink(width: number) {
|
||||
private getMode(this: LiveExampleComponent, attrs: AttrMap): typeof this.mode {
|
||||
const downloadOnly = boolFromValue(getAttrValue(attrs, 'downloadOnly'));
|
||||
const isEmbedded = boolFromValue(getAttrValue(attrs, 'embedded'));
|
||||
|
||||
const attrs = this.attrs;
|
||||
const exampleDir = this.exampleDir;
|
||||
let urlQuery = '';
|
||||
|
||||
this.mode = 'default'; // display in another browser tab by default
|
||||
|
||||
this.isEmbedded = boolFromValue(attrs.embedded);
|
||||
|
||||
if (this.isEmbedded) {
|
||||
this.mode = 'embedded'; // display embedded in the doc
|
||||
urlQuery = '?ctl=1';
|
||||
}
|
||||
|
||||
this.stackblitz = `${liveExampleBase}${exampleDir}/${this.stackblitzName}stackblitz.html${urlQuery}`;
|
||||
return downloadOnly ? 'downloadOnly'
|
||||
: isEmbedded ? 'embedded' :
|
||||
'default';
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
// The `liveExampleContent` property is set by the DocViewer when it builds this component.
|
||||
// It is the original innerHTML of the host element.
|
||||
// Angular will sanitize this title when displayed so should be plain text.
|
||||
const title = this.elementRef.nativeElement.liveExampleContent;
|
||||
this.title = (title || this.attrs.title || 'live example').trim();
|
||||
this.onResize(window.innerWidth);
|
||||
private getStackblitz(exampleDir: string, stackblitzName: string, isEmbedded: boolean) {
|
||||
const urlQuery = isEmbedded ? '?ctl=1' : '';
|
||||
return `${LIVE_EXAMPLE_BASE}${exampleDir}/${stackblitzName}stackblitz.html${urlQuery}`;
|
||||
}
|
||||
|
||||
@HostListener('window:resize', ['$event.target.innerWidth'])
|
||||
onResize(width: number) {
|
||||
if (this.mode !== 'downloadOnly') {
|
||||
this.calcStackblitzLink(width);
|
||||
}
|
||||
private getStackblitzName(attrs: AttrMap) {
|
||||
const attrValue = (getAttrValue(attrs, 'stackblitz') || '').trim();
|
||||
return attrValue && `${attrValue}.`;
|
||||
}
|
||||
|
||||
private getTitle(attrs: AttrMap) {
|
||||
return (getAttrValue(attrs, 'title') || 'live example').trim();
|
||||
}
|
||||
|
||||
private getZip(exampleDir: string, stackblitzName: string) {
|
||||
const zipName = exampleDir.split('/')[0];
|
||||
return `${ZIP_BASE}${exampleDir}/${stackblitzName}${zipName}.zip`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +137,7 @@ export class LiveExampleComponent implements OnInit {
|
||||
@Component({
|
||||
selector: 'aio-embedded-stackblitz',
|
||||
template: `<iframe #iframe frameborder="0" width="100%" height="100%"></iframe>`,
|
||||
styles: [ 'iframe { min-height: 400px; }']
|
||||
styles: [ 'iframe { min-height: 400px; }' ]
|
||||
})
|
||||
export class EmbeddedStackblitzComponent implements AfterViewInit {
|
||||
@Input() src: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ElementRef } from '@angular/core';
|
||||
|
||||
import { getAttrs, getAttrValue, getBoolFromAttribute, boolFromValue } from './attribute-utils';
|
||||
import { AttrMap, getAttrs, getAttrValue, getBoolFromAttribute, boolFromValue } from './attribute-utils';
|
||||
|
||||
describe('Attribute Utilities', () => {
|
||||
let testEl: HTMLElement;
|
||||
@ -32,17 +32,17 @@ describe('Attribute Utilities', () => {
|
||||
});
|
||||
|
||||
describe('getAttrValue', () => {
|
||||
let attrMap: { [index: string]: string };
|
||||
let attrMap: AttrMap;
|
||||
|
||||
beforeEach(() => {
|
||||
attrMap = getAttrs(testEl);
|
||||
});
|
||||
|
||||
it('should return empty string value for attribute "a"', () => {
|
||||
it('should return empty string for attribute "a"', () => {
|
||||
expect(getAttrValue(attrMap, 'a')).toBe('');
|
||||
});
|
||||
|
||||
it('should return empty string value for attribute "A"', () => {
|
||||
it('should return empty string for attribute "A"', () => {
|
||||
expect(getAttrValue(attrMap, 'A')).toBe('');
|
||||
});
|
||||
|
||||
@ -50,7 +50,7 @@ describe('Attribute Utilities', () => {
|
||||
expect(getAttrValue(attrMap, 'b')).toBe('true');
|
||||
});
|
||||
|
||||
it('should return empty string value for attribute "d-E"', () => {
|
||||
it('should return empty string for attribute "d-E"', () => {
|
||||
expect(getAttrValue(attrMap, 'd-E')).toBe('');
|
||||
});
|
||||
|
||||
@ -68,12 +68,10 @@ describe('Attribute Utilities', () => {
|
||||
expect(getAttrValue(attrMap, ['d-e', 'd'])).toBe('');
|
||||
});
|
||||
|
||||
it('should return undefined value for non-existent attribute "x"', () => {
|
||||
it('should return undefined for non-existent attributes', () => {
|
||||
expect(getAttrValue(attrMap, 'x')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined if no argument', () => {
|
||||
expect(getAttrValue(attrMap)).toBeUndefined();
|
||||
expect(getAttrValue(attrMap, '')).toBeUndefined();
|
||||
expect(getAttrValue(attrMap, ['', 'x'])).toBeUndefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,17 +1,19 @@
|
||||
// Utilities for processing HTML element attributes
|
||||
import { ElementRef } from '@angular/core';
|
||||
|
||||
interface StringMap { [index: string]: string; }
|
||||
export interface AttrMap {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attribute map from element or ElementRef `attributes`.
|
||||
* Attribute map keys are forced lowercase for case-insensitive lookup.
|
||||
* @param el The source of the attributes
|
||||
* @param el The source of the attributes.
|
||||
*/
|
||||
export function getAttrs(el: HTMLElement | ElementRef): StringMap {
|
||||
export function getAttrs(el: HTMLElement | ElementRef): AttrMap {
|
||||
const attrs: NamedNodeMap = el instanceof ElementRef ? el.nativeElement.attributes : el.attributes;
|
||||
const attrMap: StringMap = {};
|
||||
for (const attr of attrs as any /* cast due to https://github.com/Microsoft/TypeScript/issues/2695 */) {
|
||||
const attrMap: AttrMap = {};
|
||||
for (const attr of attrs as any as Attr[] /* cast due to https://github.com/Microsoft/TypeScript/issues/2695 */) {
|
||||
attrMap[attr.name.toLowerCase()] = attr.value;
|
||||
}
|
||||
return attrMap;
|
||||
@ -19,29 +21,29 @@ export function getAttrs(el: HTMLElement | ElementRef): StringMap {
|
||||
|
||||
/**
|
||||
* Return the attribute that matches `attr`.
|
||||
* @param attr Name of the attribute or a string of candidate attribute names
|
||||
* @param attr Name of the attribute or a string of candidate attribute names.
|
||||
*/
|
||||
export function getAttrValue(attrs: StringMap, attr: string | string[] = ''): string {
|
||||
return attrs[typeof attr === 'string' ?
|
||||
attr.toLowerCase() :
|
||||
attr.find(a => attrs[a.toLowerCase()] !== undefined) || ''
|
||||
];
|
||||
export function getAttrValue(attrs: AttrMap, attr: string | string[]): string | undefined {
|
||||
const key = (typeof attr === 'string')
|
||||
? attr
|
||||
: attr.find(a => attrs.hasOwnProperty(a.toLowerCase()));
|
||||
|
||||
return (key === undefined) ? undefined : attrs[key.toLowerCase()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean state of an attribute value (if supplied)
|
||||
* @param attrValue The string value of some attribute (or undefined if attribute not present)
|
||||
* @param attrValue The string value of some attribute (or undefined if attribute not present).
|
||||
* @param def Default boolean value when attribute is undefined.
|
||||
*/
|
||||
export function boolFromValue(attrValue: string|undefined, def: boolean = false) {
|
||||
// tslint:disable-next-line:triple-equals
|
||||
return attrValue == undefined ? def : attrValue.trim() !== 'false';
|
||||
export function boolFromValue(attrValue: string | undefined, def: boolean = false) {
|
||||
return attrValue === undefined ? def : attrValue.trim() !== 'false';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean state of attribute from an element
|
||||
* @param el The source of the attributes
|
||||
* @param atty Name of the attribute or a string of candidate attribute names
|
||||
* @param el The source of the attributes.
|
||||
* @param atty Name of the attribute or a string of candidate attribute names.
|
||||
* @param def Default boolean value when attribute is undefined.
|
||||
*/
|
||||
export function getBoolFromAttribute(
|
||||
|
BIN
aio/src/assets/images/logos/concept-icons/animations.png
Executable file
After Width: | Height: | Size: 4.6 KiB |
1
aio/src/assets/images/logos/concept-icons/animations.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#ff7043;}.cls-2{fill:#f4511e;}.cls-3{fill:#ffb8a1;}.cls-4{fill:#ffc6b4;}.cls-5{fill:#ffe2d9;}.cls-6{fill:#fff;}</style></defs><title>animations</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><rect class="cls-3" x="43" y="71.2" width="68.4" height="68.84" rx="4" ry="4"/><rect class="cls-4" x="57.4" y="62.3" width="68.8" height="68.84" rx="4" ry="4" transform="translate(38.6 -25.6) rotate(20)"/><rect class="cls-5" x="71.3" y="59.2" width="68.8" height="68.84" rx="4" ry="4" transform="translate(66.9 -42.1) rotate(32.5)"/><rect class="cls-6" x="81.6" y="58.3" width="68.8" height="68.84" rx="4" ry="4" transform="translate(99.6 -54.9) rotate(45)"/></g></g></svg>
|
After Width: | Height: | Size: 1.0 KiB |
BIN
aio/src/assets/images/logos/concept-icons/augury.png
Executable file
After Width: | Height: | Size: 5.2 KiB |
1
aio/src/assets/images/logos/concept-icons/augury.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#4a3493;}.cls-2{fill:#311b92;}.cls-3{opacity:0.5;}.cls-4{fill:#fff;}</style></defs><title>augury</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><g id="Group-2"><g id="Group-2-2" class="cls-3"><path id="Combined-Shape" class="cls-4" d="M142.4,90.2A44.1,44.1,0,1,1,92.7,52.8a40.3,40.3,0,0,1,6-.4,44.8,44.8,0,0,1,15.9,2.9,25.8,25.8,0,1,0,27.8,34.9Z"/></g><path id="Combined-Shape-2" class="cls-4" d="M140.6,87.8A44.1,44.1,0,1,1,90.9,50.4a40.3,40.3,0,0,1,6-.4,45.6,45.6,0,0,1,15.9,2.9,25.8,25.8,0,1,0,27.8,34.9Z"/></g></g></g></svg>
|
After Width: | Height: | Size: 908 B |
BIN
aio/src/assets/images/logos/concept-icons/cdk.png
Executable file
After Width: | Height: | Size: 2.9 KiB |
1
aio/src/assets/images/logos/concept-icons/cdk.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#03a9f4;}.cls-2{fill:#039be5;}.cls-3{fill:#fff;}</style></defs><title>cdk</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><rect class="cls-3" x="117.8" y="45" width="30" height="30" rx="1" ry="1"/><rect class="cls-3" x="117.8" y="85" width="30" height="30" rx="1" ry="1"/><rect class="cls-3" x="117.8" y="125" width="30" height="30" rx="1" ry="1"/><rect class="cls-3" x="77.8" y="125" width="30" height="30" rx="1" ry="1"/><rect class="cls-3" x="37.8" y="125" width="30" height="30" rx="1" ry="1"/><rect class="cls-3" x="37.8" y="85" width="30" height="30" rx="1" ry="1"/><rect class="cls-3" x="77.8" y="85" width="30" height="30" rx="1" ry="1"/></g></g></svg>
|
After Width: | Height: | Size: 1.0 KiB |
BIN
aio/src/assets/images/logos/concept-icons/cli.png
Executable file
After Width: | Height: | Size: 3.2 KiB |
1
aio/src/assets/images/logos/concept-icons/cli.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#37474f;}.cls-2{fill:#263238;}.cls-3{fill:#fff;}</style></defs><title>cli</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><path class="cls-3" d="M42.8,55v90h100V55ZM138,139.9H47.5V60.1h90.6v79.8Z"/><polygon class="cls-3" points="60.1 111.4 63.5 114.9 82.8 95.5 63.2 75.9 59.8 79.3 76 95.5 60.1 111.4"/><rect class="cls-3" x="82.8" y="117.2" width="30" height="4"/></g></g></svg>
|
After Width: | Height: | Size: 757 B |
BIN
aio/src/assets/images/logos/concept-icons/compiler.png
Executable file
After Width: | Height: | Size: 6.1 KiB |
1
aio/src/assets/images/logos/concept-icons/compiler.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#8bc34a;}.cls-2{fill:#7cb342;}.cls-3{fill:#fff;stroke:#fff;stroke-miterlimit:10;stroke-width:0.08px;}.cls-4{fill:#bed9a1;}</style></defs><title>compiler</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><path class="cls-3" d="M113.9,144.1l-1.5-5.5a7,7,0,0,1,2.7-7.4,26.2,26.2,0,0,0,4.8-4,36,36,0,0,0,4.1-4.8,6.7,6.7,0,0,1,7.4-2.7l5.4,1.4a1.7,1.7,0,0,0,1.4-.1c.5-.3.9-.7.9-1.1l3.7-13.8a1.9,1.9,0,0,0-1.4-2.2l-5.4-1.5a7.2,7.2,0,0,1-5.2-6,38.7,38.7,0,0,0-3.2-12.1,7.1,7.1,0,0,1,1.3-7.9l4-3.9a1.9,1.9,0,0,0,0-2.6l-10-10a1.8,1.8,0,0,0-2.5,0l-4,4a7,7,0,0,1-7.8,1.3A37.4,37.4,0,0,0,96.5,62a7.3,7.3,0,0,1-6.1-5.2L89,51.4a1.9,1.9,0,0,0-2.3-1.3L73,53.7a2.3,2.3,0,0,0-1.1.9,3.4,3.4,0,0,0-.2,1.4l1.5,5.4a6.9,6.9,0,0,1-2.7,7.4,38.3,38.3,0,0,0-4.8,4.1,47.2,47.2,0,0,0-4.1,4.8,6.8,6.8,0,0,1-7.4,2.7L48.8,79a1.7,1.7,0,0,0-1.4.1,1.9,1.9,0,0,0-.9,1.1L42.9,93.9a1.9,1.9,0,0,0,1.3,2.3l5.4,1.4a6.2,6.2,0,0,1,3,1.8,6.8,6.8,0,0,1,2.1,4.2,38.7,38.7,0,0,0,3.2,12.1,6.8,6.8,0,0,1-1.3,7.9l-4,3.9a1.9,1.9,0,0,0,0,2.6l10,10a1.9,1.9,0,0,0,2.6,0l3.9-4a6.8,6.8,0,0,1,7.9-1.3A36.8,36.8,0,0,0,89.1,138a7.2,7.2,0,0,1,6,5.2l1.5,5.4a1.7,1.7,0,0,0,2.2,1.3l13.8-3.5a2.3,2.3,0,0,0,1.1-.9A1.8,1.8,0,0,0,113.9,144.1ZM76.5,116.3a23,23,0,1,1,32.5,0A23.2,23.2,0,0,1,76.5,116.3Z"/><ellipse class="cls-4" cx="92.8" cy="100" rx="13.3" ry="13.3"/></g></g></svg>
|
After Width: | Height: | Size: 1.6 KiB |
BIN
aio/src/assets/images/logos/concept-icons/components.png
Executable file
After Width: | Height: | Size: 4.7 KiB |
1
aio/src/assets/images/logos/concept-icons/components.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#448aff;}.cls-2{fill:#2979ff;}.cls-3{fill:#fff;}.cls-4{fill:#a2c5ff;}</style></defs><title>components</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-3" points="73.6 131.4 54.3 98 84.3 46.1 62.8 46.1 32.8 98 62.8 150 84.4 150 73.6 131.4 73.6 131.4"/><polygon class="cls-4" points="152.8 98 122.8 46.1 84.3 46.1 54.3 98 73.6 64.7 112.1 64.7 131.3 98 112.1 131.4 73.6 131.4 84.4 150 122.8 150 152.8 98"/></g></g></svg>
|
After Width: | Height: | Size: 815 B |
BIN
aio/src/assets/images/logos/concept-icons/dependency-injection.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><style>.cls-1{fill:#546e7a;}.cls-2{fill:#455a64;}.cls-3,.cls-4{fill:#fff;}.cls-3{opacity:0.5;}</style></defs><title>dependency-injection</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,100A100,100,0,0,0,100,200V0A100,100,0,0,0,0,100Z"/><path class="cls-2" d="M100,0V200A100,100,0,0,0,100,0Z"/><polygon class="cls-3" points="131.2 73.2 151 47.7 125.6 67.5 108.6 61.8 59.1 111.3 87.4 139.6 136.9 90.1 131.2 73.2"/><rect class="cls-4" x="74.5" y="74.3" width="40" height="60" transform="translate(101.4 -36.3) rotate(45)"/><rect class="cls-4" x="66.8" y="107" width="20" height="30" transform="translate(108.7 -18.6) rotate(45)"/><rect class="cls-4" x="42.6" y="131.1" width="40" height="10" transform="translate(114.6 -4.4) rotate(45)"/></g></g></svg>
|
After Width: | Height: | Size: 876 B |
BIN
aio/src/assets/images/logos/concept-icons/forms.png
Executable file
After Width: | Height: | Size: 3.4 KiB |
1
aio/src/assets/images/logos/concept-icons/forms.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#e57373;}.cls-2{fill:#ef5350;}.cls-3{fill:#fff;}</style></defs><title>forms</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><path class="cls-3" d="M138.7,90H47c-2.4,0-4-2.3-4-5.6V55.6c0-3.3,1.6-5.6,4-5.6h92.1c2.3,0,3.9,2.3,3.9,5.6V84.4C142.6,87.7,141,90,138.7,90Z"/><path class="cls-3" d="M139.8,120H96.3c-2,0-3.3-1.4-3.3-3.6V103.6c0-2.2,1.3-3.6,3.3-3.6h43.5c1.9,0,3.2,1.4,3.2,3.6v12.8A3.4,3.4,0,0,1,139.8,120Z"/><path class="cls-3" d="M139.8,150H96.3c-2,0-3.3-1.5-3.3-3.8V133.8c0-2.3,1.3-3.8,3.3-3.8h43.5c1.9,0,3.2,1.5,3.2,3.8v12.4C143,148.1,141.7,150,139.8,150Z"/><rect class="cls-3" x="43" y="100" width="40" height="50" rx="4" ry="4"/></g></g></svg>
|
After Width: | Height: | Size: 1.0 KiB |
BIN
aio/src/assets/images/logos/concept-icons/http.png
Executable file
After Width: | Height: | Size: 4.7 KiB |
1
aio/src/assets/images/logos/concept-icons/http.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#2e7d32;}.cls-2{fill:#1b5e20;}.cls-3,.cls-4,.cls-5{fill:#fff;stroke:#fff;stroke-miterlimit:10;}.cls-3{stroke-width:0.24px;}.cls-4{stroke-width:0.27px;}.cls-5{stroke-width:0.27px;}</style></defs><title>http</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-3" points="107.5 150 100.3 148.2 125.7 50 132.9 51.8 107.5 150"/><polygon class="cls-3" points="81.5 150 74.3 148.2 99.7 50 106.8 51.8 81.5 150"/><circle class="cls-4" cx="65.5" cy="82.8" r="7.1"/><circle class="cls-5" cx="65.5" cy="113.1" r="7.1"/></g></g></svg>
|
After Width: | Height: | Size: 916 B |
BIN
aio/src/assets/images/logos/concept-icons/i18n.png
Executable file
After Width: | Height: | Size: 7.1 KiB |
1
aio/src/assets/images/logos/concept-icons/i18n.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#4caf50;}.cls-2{fill:#388e3c;}.cls-3{fill:#fff;}</style></defs><title>i18n</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><path class="cls-3" d="M93,150a50,50,0,0,1-50-50A49.3,49.3,0,0,1,71.4,55.1,43.5,43.5,0,0,1,82,51.3,41.1,41.1,0,0,1,92.6,50c27.4,0,50,22.4,50.4,50a49.5,49.5,0,0,1-17.3,37.7,47.7,47.7,0,0,1-21.7,11A42.5,42.5,0,0,1,93,150Zm-.4-95.9a39,39,0,0,0-9.7,1.1,47.2,47.2,0,0,0-9.7,3.5A45.4,45.4,0,0,0,47.1,100,46,46,0,0,0,93,145.9a45.3,45.3,0,0,0,10.1-1.1A43.1,43.1,0,0,0,123,134.6,45.5,45.5,0,0,0,139,100C138.6,74.7,117.8,54.1,92.6,54.1Z"/><rect class="cls-3" x="90.9" y="54.1" width="3.9" height="91.78"/><path class="cls-3" d="M92.8,147.8c-16.3,0-29.7-21.5-29.7-48s13.4-48,29.7-48,29.7,21.5,29.7,48S109.2,147.8,92.8,147.8Zm0-92.1C78.6,55.7,67,75.5,67,99.8s11.6,44.1,25.8,44.1,25.8-19.8,25.8-44.1S107,55.7,92.8,55.7Z"/><rect class="cls-3" x="47.1" y="97.9" width="91.8" height="3.91"/><rect class="cls-3" x="53" y="76" width="80.5" height="3.91"/><rect class="cls-3" x="53" y="117.8" width="80.5" height="3.91"/></g></g></svg>
|
After Width: | Height: | Size: 1.4 KiB |
BIN
aio/src/assets/images/logos/concept-icons/karma.png
Executable file
After Width: | Height: | Size: 5.0 KiB |
1
aio/src/assets/images/logos/concept-icons/karma.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#3dbeae;}.cls-2{fill:#349b8b;}.cls-3,.cls-4{fill:#fff;}.cls-4{opacity:0.5;isolation:isolate;}</style></defs><title>karma</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-3" points="76.6 59.9 99.7 59.9 99.7 82.2 115.5 59.9 140.1 59.9 99.9 119.2 99.9 139.9 92.4 139.9 76.6 84.2 76.6 59.9"/><polygon class="cls-4" points="143 139.9 114.4 97.8 101.8 116.4 118.2 139.9 143 139.9"/><polygon class="cls-3" points="39 84.2 51.3 128.4 69.6 95.6 57.7 106.3 39 84.2"/><polygon class="cls-4" points="80.7 139.1 69.6 95.6 51.3 128.4 62.8 117.3 80.7 139.1"/></g></g></svg>
|
After Width: | Height: | Size: 950 B |
BIN
aio/src/assets/images/logos/concept-icons/labs.png
Executable file
After Width: | Height: | Size: 5.6 KiB |
1
aio/src/assets/images/logos/concept-icons/labs.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 179.2 192.7"><defs><style>.cls-1{fill:#1de9b6;}.cls-2{fill:#00bfa5;}.cls-3{fill:#bbf8e9;}.cls-4{fill:#fff;}</style></defs><title>labs</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="89.4 0 89.4 0 89.4 0 0 32 13.5 150.4 89.4 192.7 89.4 192.7 89.4 192.7 165.4 150.4 179.2 32 89.4 0"/><polygon class="cls-2" points="89.4 0 89.4 21.4 89.4 21.4 89.4 118.7 89.4 118.7 89.4 192.7 89.4 192.7 165.4 150.4 179.2 32 89.4 0"/><path class="cls-3" d="M124.1,75.8l-37-11.5a2.8,2.8,0,0,0-3.5,1.9l-.2.5a2.9,2.9,0,0,0,1.9,3.5l7.1,2.2L85.2,95.5a30.4,30.4,0,0,0,1.7,60.7A30.7,30.7,0,0,0,98,153.8h0l1.5-.7a30.5,30.5,0,0,0,4.8-51.5l7.2-23.3,10.7,3.4a3,3,0,0,0,3.6-1.9v-.5A2.7,2.7,0,0,0,124.1,75.8Z"/><ellipse class="cls-4" cx="90.4" cy="44.1" rx="7.8" ry="7.9"/><ellipse class="cls-4" cx="126.8" cy="60.3" rx="3.8" ry="3.8"/><ellipse class="cls-4" cx="51.5" cy="73.9" rx="4.9" ry="4.9"/><path class="cls-4" d="M111.3,134.2a26.3,26.3,0,1,1-50.2-15.6"/></g></g></svg>
|
After Width: | Height: | Size: 1.0 KiB |
BIN
aio/src/assets/images/logos/concept-icons/language-services.png
Executable file
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#5c6bc0;}.cls-2{fill:#3949ab;}.cls-3{fill:#fff;}.cls-4{fill:#aeb5e0;}</style></defs><title>language-services</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><path class="cls-3" d="M93,50a50,50,0,1,0,50,50A50,50,0,0,0,93,50Zm-5.3,80.3L68.9,111.5l6.7-6.7L86,115.2l24-38.8,8,5Z"/><polygon class="cls-4" points="86 115.2 75.6 104.8 68.9 111.5 87.7 130.3 118 81.4 110 76.4 86 115.2"/></g></g></svg>
|
After Width: | Height: | Size: 766 B |
BIN
aio/src/assets/images/logos/concept-icons/lazy-loading.png
Executable file
After Width: | Height: | Size: 3.7 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><style>.cls-1{fill:#546e7a;}.cls-2{fill:#455a64;}.cls-3{fill:#fff;}</style></defs><title>lazy-loading</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,100A100,100,0,0,0,100,200V0A100,100,0,0,0,0,100Z"/><path class="cls-2" d="M100,0V200A100,100,0,0,0,100,0Z"/><path class="cls-3" d="M120,93.7a24.4,24.4,0,0,0,10.1,2.1,24.9,24.9,0,1,0-20.3-10.6l-10,10.1-9.8-9.8a24.5,24.5,0,0,0,4.7-14.6,24.7,24.7,0,1,0-15,22.9l10.8,10.8L47.7,147.5l3.7,3.8a7.9,7.9,0,0,0,11.2,0L99.8,114l37.6,37.7a7.9,7.9,0,0,0,11.2,0l3.7-3.8-43.2-43.3ZM109.8,70.9a20.4,20.4,0,1,1,20.3,20.4,20.8,20.8,0,0,1-6.6-1.1,20.5,20.5,0,0,1-13.7-19.3ZM76.2,90.3a18.9,18.9,0,0,1-6.3,1,20.4,20.4,0,1,1,20.3-20.4,20.6,20.6,0,0,1-3.4,11.3A20.3,20.3,0,0,1,76.2,90.3Z"/></g></g></svg>
|
After Width: | Height: | Size: 858 B |
BIN
aio/src/assets/images/logos/concept-icons/libraries.png
Executable file
After Width: | Height: | Size: 4.0 KiB |
1
aio/src/assets/images/logos/concept-icons/libraries.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><style>.cls-1{fill:#546e7a;}.cls-2{fill:#455a64;}.cls-3,.cls-4{fill:#fff;}.cls-4{opacity:0.5;}</style></defs><title>libraries</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,100A100,100,0,0,0,100,200V0A100,100,0,0,0,0,100Z"/><path class="cls-2" d="M100,0V200A100,100,0,0,0,100,0Z"/><path class="cls-3" d="M25,63.3v75H58.3v-75Zm25,60H33.3V120H50ZM50,90H33.3V86.6H50Zm0-8.4H33.3V78.3H50Z"/><rect class="cls-4" x="33.3" y="77.9" width="16.7" height="4"/><rect class="cls-4" x="33.3" y="86.6" width="16.7" height="3.34"/><rect class="cls-4" x="33.3" y="120" width="16.7" height="3.34"/><path class="cls-3" d="M65,63.3v75H98.3v-75Zm25,60H73.3V120H90ZM90,90H73.3V86.6H90Zm0-8.4H73.3V78.3H90Z"/><rect class="cls-4" x="73.3" y="78.3" width="16.7" height="3.34"/><rect class="cls-4" x="73.3" y="86.6" width="16.7" height="3.34"/><rect class="cls-4" x="73.3" y="120" width="16.7" height="3.34"/><path class="cls-3" d="M98.3,85.3l53.1,53L175,114.7l-53.1-53ZM158.5,110l-11.8,11.8-2.3-2.3,11.8-11.8ZM134.9,86.4,123.1,98.2l-2.3-2.3,11.8-11.8ZM129,80.5,117.2,92.3,114.9,90l11.8-11.8Z"/><rect class="cls-4" x="113.6" y="83.6" width="16.7" height="3.34" transform="translate(-24.6 111.2) rotate(-45)"/><rect class="cls-4" x="119.5" y="89.5" width="16.7" height="3.34" transform="translate(-27 117.1) rotate(-45)"/><rect class="cls-4" x="143.1" y="113.1" width="16.7" height="3.34" transform="translate(-36.8 140.7) rotate(-45)"/></g></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
BIN
aio/src/assets/images/logos/concept-icons/material.png
Executable file
After Width: | Height: | Size: 5.2 KiB |
1
aio/src/assets/images/logos/concept-icons/material.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 179.2 192.7"><defs><style>.cls-1{fill:#ffa726;}.cls-2{fill:#fb8c00;}.cls-3{fill:#ffe0b2;}.cls-4{fill:#fff3e0;}.cls-5{fill:#fff;}</style></defs><title>material</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="89.4 0 89.4 0 89.4 0 0 32 13.5 150.4 89.4 192.7 89.4 192.7 89.4 192.7 165.4 150.4 179.2 32 89.4 0"/><polygon class="cls-2" points="89.4 0 89.4 21.4 89.4 21.4 89.4 118.7 89.4 118.7 89.4 192.7 89.4 192.7 165.4 150.4 179.2 32 89.4 0"/><polygon class="cls-3" points="102.9 146.3 39.6 115.8 75.9 93.4 139.6 124 102.9 146.3"/><polygon class="cls-4" points="102.9 122.8 39.6 92.2 75.9 69.9 139.6 100.5 102.9 122.8"/><polygon class="cls-5" points="102.9 99.3 39.6 68.7 75.9 46.3 139.6 76.9 102.9 99.3"/></g></g></svg>
|
After Width: | Height: | Size: 833 B |
BIN
aio/src/assets/images/logos/concept-icons/performance.png
Executable file
After Width: | Height: | Size: 5.4 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><style>.cls-1{fill:#546e7a;}.cls-2{fill:#455a64;}.cls-3{fill:#bbc5ca;}.cls-4{fill:#fff;}.cls-5{fill:none;}</style></defs><title>performance</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,100A100,100,0,0,0,100,200V0A100,100,0,0,0,0,100Z"/><path class="cls-2" d="M100,0V200A100,100,0,0,0,100,0Z"/><circle class="cls-3" cx="100" cy="100" r="50"/><circle class="cls-4" cx="100" cy="100" r="8.33"/><rect class="cls-4" x="94.82" y="85.42" width="35.36" height="4.17" transform="translate(-28.92 105.18) rotate(-45)"/><path class="cls-5" d="M100,59.09A41,41,0,0,0,59.09,100h81.82A41,41,0,0,0,100,59.09Z"/><path class="cls-5" d="M100,140.91A41,41,0,0,0,140.91,100H59.09A41,41,0,0,0,100,140.91Z"/><path class="cls-4" d="M100,50a50,50,0,0,0-50,50h9.09a40.91,40.91,0,0,1,81.82,0H150A50,50,0,0,0,100,50Z"/></g></g></svg>
|
After Width: | Height: | Size: 936 B |
BIN
aio/src/assets/images/logos/concept-icons/protractor.png
Executable file
After Width: | Height: | Size: 4.8 KiB |
1
aio/src/assets/images/logos/concept-icons/protractor.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#e13439;}.cls-2{fill:#b52f32;}.cls-3{fill:#fff;}</style></defs><title>protractor</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><path class="cls-3" d="M145.3,117.1v-3.6H158a64.9,64.9,0,0,0-18-43.1L130.4,80l-2.5-2.5,9.5-9.6A64.3,64.3,0,0,0,95.3,50.4V63H91.7V50.3A65,65,0,0,0,48.6,67.9l9.6,9.6L55.6,80,46,70.4a64.8,64.8,0,0,0-17.9,43.1H40.7v3.6H28v14.8H158V117.1Zm-93.5-2.2a41.3,41.3,0,1,1,82.5,0Z"/></g></g></svg>
|
After Width: | Height: | Size: 786 B |
BIN
aio/src/assets/images/logos/concept-icons/pwa.png
Executable file
After Width: | Height: | Size: 4.9 KiB |
1
aio/src/assets/images/logos/concept-icons/pwa.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#9c27b0;}.cls-2{fill:#7b1fa2;}.cls-3,.cls-4{fill:#fff;}.cls-4{opacity:0.8;}</style></defs><title>pwa</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><path class="cls-3" d="M123.2,115.4l3.7-9.3h10.7L132.5,92l6.4-16L157,124H143.6l-3.1-8.6Z"/><path class="cls-4" d="M111.8,124l19.4-48H118.4l-13.3,31L95.6,76H85.7L75.6,107,68.4,92.9l-6.5,19.9L68.5,124H81.2l9.1-27.8L99.1,124Z"/><path class="cls-3" d="M41.2,107.5h8a21.2,21.2,0,0,0,6.4-.8l2.1-6.3,5.7-17.6a9,9,0,0,0-1.5-1.9C58.9,77.6,54.6,76,49,76H29v48H41.2ZM51.7,87a6.3,6.3,0,0,1,1.8,4.7A6.7,6.7,0,0,1,52,96.3c-1.2,1.3-3.2,1.9-6.2,1.9H41.2V85.3h4.7C48.6,85.3,50.6,85.9,51.7,87Z"/></g></g></svg>
|
After Width: | Height: | Size: 1014 B |
BIN
aio/src/assets/images/logos/concept-icons/router.png
Executable file
After Width: | Height: | Size: 3.5 KiB |
1
aio/src/assets/images/logos/concept-icons/router.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 185.6 200"><defs><style>.cls-1{fill:#1565c0;}.cls-2{fill:#0d47a1;}.cls-3{fill:#fff;}.cls-4{fill:#86a3d0;}</style></defs><title>router</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.4 0 92.4 0 92.4 0 0 33.3 14 156.1 92.4 200 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-2" points="92.4 0 92.4 22.2 92.4 22.2 92.4 123.2 92.4 123.2 92.4 200 92.4 200 171.3 156.1 185.6 33.3 92.4 0"/><polygon class="cls-3" points="76.1 128.9 42.8 139.9 42.8 60.9 76.1 49.9 76.1 128.9"/><polygon class="cls-3" points="142.8 128.9 109.5 139.9 109.5 60.9 142.8 49.9 142.8 128.9"/><polygon class="cls-4" points="109.5 139.9 76.1 128.9 76.1 49.9 109.5 60.9 109.5 139.9"/></g></g></svg>
|
After Width: | Height: | Size: 805 B |
BIN
aio/src/assets/images/logos/concept-icons/templates.png
Executable file
After Width: | Height: | Size: 3.0 KiB |
1
aio/src/assets/images/logos/concept-icons/templates.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><style>.cls-1{fill:#546e7a;}.cls-2{fill:#455a64;}.cls-3{fill:#a2adb2;}.cls-4{fill:#e3e6e8;}.cls-5{fill:#fff;}</style></defs><title>templates</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M0,100A100,100,0,0,0,100,200V0A100,100,0,0,0,0,100Z"/><path class="cls-2" d="M100,0V200A100,100,0,0,0,100,0Z"/><rect class="cls-3" x="80" y="70" width="60" height="80"/><rect class="cls-4" x="70" y="60" width="60" height="80"/><rect class="cls-5" x="60" y="50" width="60" height="80"/></g></g></svg>
|
After Width: | Height: | Size: 612 B |
BIN
aio/src/assets/images/logos/concept-icons/universal.png
Executable file
After Width: | Height: | Size: 3.6 KiB |
1
aio/src/assets/images/logos/concept-icons/universal.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 186 200"><defs><style>.cls-1{fill:#00acc1;}.cls-2{fill:#00838f;}.cls-3{fill:#fff;}.cls-4{fill:#80d6e0;}</style></defs><title>universal</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="92.8 0 92.8 0 92.8 0 0 33.3 14 156.1 92.8 200 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><polygon class="cls-2" points="92.8 0 92.8 22.2 92.8 22.2 92.8 123.2 92.8 123.2 92.8 200 92.8 200 171.7 156.1 186 33.3 92.8 0"/><path class="cls-3" d="M121,40H65A12,12,0,0,0,53,52v96a12,12,0,0,0,12,12h56a12,12,0,0,0,12-12V52A12,12,0,0,0,121,40ZM93,150a10,10,0,1,1,10-10A10,10,0,0,1,93,150Zm30-44a4,4,0,0,1-4,4H67a4,4,0,0,1-4-4V94a4,4,0,0,1,4-4h52a4,4,0,0,1,4,4Zm0-30a4,4,0,0,1-4,4H67a4,4,0,0,1-4-4V64a4,4,0,0,1,4-4h52a4,4,0,0,1,4,4Z"/><rect class="cls-4" x="63" y="60" width="60" height="20" rx="4" ry="4"/><rect class="cls-4" x="63" y="90" width="60" height="20" rx="4" ry="4"/><circle class="cls-4" cx="93" cy="140" r="10"/></g></g></svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -67,8 +67,8 @@
|
||||
}
|
||||
|
||||
img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
width: auto;
|
||||
margin-bottom: 8px * 2;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
"devDependencies": [
|
||||
"@angular/cli",
|
||||
"@types/jasminewd2",
|
||||
"jasmine-marbles",
|
||||
"jasmine-spec-reporter",
|
||||
"karma-coverage-istanbul-reporter",
|
||||
"ts-node"
|
||||
|
@ -98,6 +98,7 @@ class ExampleZipper {
|
||||
'src/favicon.ico',
|
||||
'src/karma.conf.js',
|
||||
'src/polyfills.ts',
|
||||
'src/test.ts',
|
||||
'src/typings.d.ts',
|
||||
'src/environments/**/*',
|
||||
'src/tsconfig.*',
|
||||
|
@ -11,7 +11,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/angular.io-example",
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
|
@ -1,5 +1,5 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
|
@ -11,7 +11,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/angular.io-example",
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/angular.io-example",
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
|
@ -40,11 +40,11 @@
|
||||
"zone.js": "^0.8.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.6.0",
|
||||
"@angular/cli": "^6.0.0",
|
||||
"@angular/compiler-cli": "^6.0.0",
|
||||
"@angular/language-service": "^6.0.0",
|
||||
"@angular/platform-server": "^6.0.0",
|
||||
"@angular-devkit/build-angular": "~0.6.0",
|
||||
"@types/angular": "^1.5.16",
|
||||
"@types/angular-animate": "^1.5.5",
|
||||
"@types/angular-cookies": "^1.4.2",
|
||||
@ -66,6 +66,7 @@
|
||||
"html-webpack-plugin": "^2.16.1",
|
||||
"http-server": "^0.9.0",
|
||||
"jasmine-core": "~2.99.1",
|
||||
"jasmine-marbles": "^0.3.1",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~1.7.1",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
|
@ -4986,6 +4986,12 @@ jasmine-core@~2.99.1:
|
||||
version "2.99.1"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.99.1.tgz#e6400df1e6b56e130b61c4bcd093daa7f6e8ca15"
|
||||
|
||||
jasmine-marbles@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-marbles/-/jasmine-marbles-0.3.1.tgz#ef65edecb41b8dd62fc6bda40448222042e32043"
|
||||
dependencies:
|
||||
lodash "^4.5.0"
|
||||
|
||||
jasmine-spec-reporter@~4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz#1d632aec0341670ad324f92ba84b4b32b35e9e22"
|
||||
|
@ -29,7 +29,7 @@ following products on your development machine:
|
||||
* [Java Development Kit](http://www.oracle.com/technetwork/es/java/javase/downloads/index.html) which is used
|
||||
to execute the selenium standalone server for e2e testing.
|
||||
|
||||
* (Optional for now) [Bazel](https://bazel.build/), please follow instructions in [Bazel.md]
|
||||
* (Optional for now) [Bazel](https://bazel.build/), please follow instructions in [BAZEL.md](https://github.com/angular/angular/blob/master/docs/BAZEL.md)
|
||||
|
||||
## Getting the Sources
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "6.0.2",
|
||||
"version": "6.0.3",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
|
@ -10,29 +10,60 @@ import {Inject, Injectable, InjectionToken, NgZone} from '@angular/core';
|
||||
|
||||
import {getDOM} from '../dom_adapter';
|
||||
|
||||
/**
|
||||
* The injection token for the event-manager plug-in service.
|
||||
*/
|
||||
export const EVENT_MANAGER_PLUGINS =
|
||||
new InjectionToken<EventManagerPlugin[]>('EventManagerPlugins');
|
||||
|
||||
/**
|
||||
* An injectable service that provides event management for Angular
|
||||
* through a browser plug-in.
|
||||
*/
|
||||
@Injectable()
|
||||
export class EventManager {
|
||||
private _plugins: EventManagerPlugin[];
|
||||
private _eventNameToPlugin = new Map<string, EventManagerPlugin>();
|
||||
|
||||
/**
|
||||
* Initializes an instance of the event-manager service.
|
||||
*/
|
||||
constructor(@Inject(EVENT_MANAGER_PLUGINS) plugins: EventManagerPlugin[], private _zone: NgZone) {
|
||||
plugins.forEach(p => p.manager = this);
|
||||
this._plugins = plugins.slice().reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler for a specific element and event.
|
||||
*
|
||||
* @param element The HTML element to receive event notifications.
|
||||
* @param eventName The name of the event to listen for.
|
||||
* @param handler A function to call when the notification occurs. Receives the
|
||||
* event object as an argument.
|
||||
* @returns A callback function that can be used to remove the handler.
|
||||
*/
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
const plugin = this._findPluginFor(eventName);
|
||||
return plugin.addEventListener(element, eventName, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a global handler for an event in a target view.
|
||||
*
|
||||
* @param target A target for global event notifications. One of "window", "document", or "body".
|
||||
* @param eventName The name of the event to listen for.
|
||||
* @param handler A function to call when the notification occurs. Receives the
|
||||
* event object as an argument.
|
||||
* @returns A callback function that can be used to remove the handler.
|
||||
*/
|
||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
||||
const plugin = this._findPluginFor(eventName);
|
||||
return plugin.addGlobalEventListener(target, eventName, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the compilation zone in which event listeners are registered.
|
||||
*/
|
||||
getZone(): NgZone { return this._zone; }
|
||||
|
||||
/** @internal */
|
||||
|
@ -12,6 +12,9 @@ import {DOCUMENT} from '../dom_tokens';
|
||||
|
||||
import {EventManagerPlugin} from './event_manager';
|
||||
|
||||
/**
|
||||
* Supported HammerJS recognizer event names.
|
||||
*/
|
||||
const EVENT_NAMES = {
|
||||
// pan
|
||||
'pan': true,
|
||||
@ -51,8 +54,8 @@ const EVENT_NAMES = {
|
||||
};
|
||||
|
||||
/**
|
||||
* A DI token that you can use to provide{@link HammerGestureConfig} to Angular. Use it to configure
|
||||
* Hammer gestures.
|
||||
* DI token for providing [HammerJS](http://hammerjs.github.io/) support to Angular.
|
||||
* @see `HammerGestureConfig`
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
@ -64,14 +67,44 @@ export interface HammerInstance {
|
||||
}
|
||||
|
||||
/**
|
||||
* An injectable [HammerJS Manager](http://hammerjs.github.io/api/#hammer.manager)
|
||||
* for gesture recognition. Configures specific event recognition.
|
||||
* @experimental
|
||||
*/
|
||||
@Injectable()
|
||||
export class HammerGestureConfig {
|
||||
/**
|
||||
* A set of supported event names for gestures to be used in Angular.
|
||||
* Angular supports all built-in recognizers, as listed in
|
||||
* [HammerJS documentation](http://hammerjs.github.io/).
|
||||
*/
|
||||
events: string[] = [];
|
||||
|
||||
/**
|
||||
* Maps gesture event names to a set of configuration options
|
||||
* that specify overrides to the default values for specific properties.
|
||||
*
|
||||
* The key is a supported event name to be configured,
|
||||
* and the options object contains a set of properties, with override values
|
||||
* to be applied to the named recognizer event.
|
||||
* For example, to disable recognition of the rotate event, specify
|
||||
* `{"rotate": {"enable": false}}`.
|
||||
*
|
||||
* Properties that are not present take the HammerJS default values.
|
||||
* For information about which properties are supported for which events,
|
||||
* and their allowed and default values, see
|
||||
* [HammerJS documentation](http://hammerjs.github.io/).
|
||||
*
|
||||
*/
|
||||
overrides: {[key: string]: Object} = {};
|
||||
|
||||
/**
|
||||
* Properties whose default values can be overridden for a given event.
|
||||
* Different sets of properties apply to different events.
|
||||
* For information about which properties are supported for which events,
|
||||
* and their allowed and default values, see
|
||||
* [HammerJS documentation](http://hammerjs.github.io/).
|
||||
*/
|
||||
options?: {
|
||||
cssProps?: any; domEvents?: boolean; enable?: boolean | ((manager: any) => boolean);
|
||||
preset?: any[];
|
||||
@ -81,8 +114,14 @@ export class HammerGestureConfig {
|
||||
inputTarget?: EventTarget;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a [HammerJS Manager](http://hammerjs.github.io/api/#hammer.manager)
|
||||
* and attaches it to a given HTML element.
|
||||
* @param element The element that will recognize gestures.
|
||||
* @returns A HammerJS event-manager object.
|
||||
*/
|
||||
buildHammer(element: HTMLElement): HammerInstance {
|
||||
const mc = new Hammer(element, this.options);
|
||||
const mc = new Hammer !(element, this.options);
|
||||
|
||||
mc.get('pinch').set({enable: true});
|
||||
mc.get('rotate').set({enable: true});
|
||||
|
@ -13,7 +13,14 @@ import {DOCUMENT} from '../dom_tokens';
|
||||
|
||||
import {EventManagerPlugin} from './event_manager';
|
||||
|
||||
/**
|
||||
* Defines supported modifiers for key events.
|
||||
*/
|
||||
const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift'];
|
||||
|
||||
/**
|
||||
* Retrieves modifiers from key-event objects.
|
||||
*/
|
||||
const MODIFIER_KEY_GETTERS: {[key: string]: (event: KeyboardEvent) => boolean} = {
|
||||
'alt': (event: KeyboardEvent) => event.altKey,
|
||||
'control': (event: KeyboardEvent) => event.ctrlKey,
|
||||
@ -23,13 +30,31 @@ const MODIFIER_KEY_GETTERS: {[key: string]: (event: KeyboardEvent) => boolean} =
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
* A browser plug-in that provides support for handling of key events in Angular.
|
||||
*/
|
||||
@Injectable()
|
||||
export class KeyEventsPlugin extends EventManagerPlugin {
|
||||
/**
|
||||
* Initializes an instance of the browser plug-in.
|
||||
* @param doc The document in which key events will be detected.
|
||||
*/
|
||||
constructor(@Inject(DOCUMENT) doc: any) { super(doc); }
|
||||
|
||||
/**
|
||||
* Reports whether a named key event is supported.
|
||||
* @param eventName The event name to query.
|
||||
* @return True if the named key event is supported.
|
||||
*/
|
||||
supports(eventName: string): boolean { return KeyEventsPlugin.parseEventName(eventName) != null; }
|
||||
|
||||
/**
|
||||
* Registers a handler for a specific element and key event.
|
||||
* @param element The HTML element to receive event notifications.
|
||||
* @param eventName The name of the key event to listen for.
|
||||
* @param handler A function to call when the notification occurs. Receives the
|
||||
* event object as an argument.
|
||||
* @returns The key event that was registered.
|
||||
*/
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
const parsedEvent = KeyEventsPlugin.parseEventName(eventName) !;
|
||||
|
||||
@ -93,6 +118,13 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
||||
return fullKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a handler callback for a key event.
|
||||
* @param fullKey The event name that combines all simultaneous keystrokes.
|
||||
* @param handler The function that responds to the key event.
|
||||
* @param zone The zone in which the event occurred.
|
||||
* @returns A callback function.
|
||||
*/
|
||||
static eventCallback(fullKey: any, handler: Function, zone: NgZone): Function {
|
||||
return (event: any /** TODO #9100 */) => {
|
||||
if (KeyEventsPlugin.getEventFullKey(event) === fullKey) {
|
||||
|
@ -6,8 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {isPlatformBrowser} from '@angular/common';
|
||||
import {Inject, PLATFORM_ID} from '@angular/core';
|
||||
import {ConnectableObservable, Observable, concat, defer, fromEvent, of , throwError} from 'rxjs';
|
||||
import {filter, map, publish, switchMap, take, tap} from 'rxjs/operators';
|
||||
|
||||
@ -71,11 +69,8 @@ export class NgswCommChannel {
|
||||
*/
|
||||
readonly events: Observable<TypedEvent>;
|
||||
|
||||
constructor(
|
||||
private serviceWorker: ServiceWorkerContainer|undefined,
|
||||
@Inject(PLATFORM_ID) platformId: string) {
|
||||
if (!serviceWorker || !isPlatformBrowser(platformId)) {
|
||||
this.serviceWorker = undefined;
|
||||
constructor(private serviceWorker: ServiceWorkerContainer|undefined) {
|
||||
if (!serviceWorker) {
|
||||
this.worker = this.events = this.registration = errorObservable(ERR_SW_NOT_SUPPORTED);
|
||||
} else {
|
||||
const controllerChangeEvents =
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
import {isPlatformBrowser} from '@angular/common';
|
||||
import {APP_INITIALIZER, ApplicationRef, InjectionToken, Injector, ModuleWithProviders, NgModule, PLATFORM_ID} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
import {filter, take} from 'rxjs/operators';
|
||||
|
||||
import {NgswCommChannel} from './low_level';
|
||||
@ -53,7 +52,8 @@ export function ngswAppInitializer(
|
||||
export function ngswCommChannelFactory(
|
||||
opts: RegistrationOptions, platformId: string): NgswCommChannel {
|
||||
return new NgswCommChannel(
|
||||
opts.enabled !== false ? navigator.serviceWorker : undefined, platformId);
|
||||
isPlatformBrowser(platformId) && opts.enabled !== false ? navigator.serviceWorker :
|
||||
undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,9 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {PLATFORM_ID} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {NgswCommChannel} from '../src/low_level';
|
||||
import {RegistrationOptions, ngswCommChannelFactory} from '../src/module';
|
||||
import {SwPush} from '../src/push';
|
||||
import {SwUpdate} from '../src/update';
|
||||
import {MockServiceWorkerContainer, MockServiceWorkerRegistration} from '../testing/mock';
|
||||
@ -19,12 +21,12 @@ import {MockServiceWorkerContainer, MockServiceWorkerRegistration} from '../test
|
||||
let comm: NgswCommChannel;
|
||||
beforeEach(() => {
|
||||
mock = new MockServiceWorkerContainer();
|
||||
comm = new NgswCommChannel(mock as any, 'browser');
|
||||
comm = new NgswCommChannel(mock as any);
|
||||
});
|
||||
describe('NgswCommsChannel', () => {
|
||||
it('can access the registration when it comes before subscription', (done: DoneFn) => {
|
||||
const mock = new MockServiceWorkerContainer();
|
||||
const comm = new NgswCommChannel(mock as any, 'browser');
|
||||
const comm = new NgswCommChannel(mock as any);
|
||||
const regPromise = mock.getRegistration() as any as MockServiceWorkerRegistration;
|
||||
|
||||
mock.setupSw();
|
||||
@ -33,18 +35,101 @@ import {MockServiceWorkerContainer, MockServiceWorkerRegistration} from '../test
|
||||
});
|
||||
it('can access the registration when it comes after subscription', (done: DoneFn) => {
|
||||
const mock = new MockServiceWorkerContainer();
|
||||
const comm = new NgswCommChannel(mock as any, 'browser');
|
||||
const comm = new NgswCommChannel(mock as any);
|
||||
const regPromise = mock.getRegistration() as any as MockServiceWorkerRegistration;
|
||||
|
||||
(comm as any).registration.subscribe((reg: any) => { done(); });
|
||||
|
||||
mock.setupSw();
|
||||
});
|
||||
it('is disabled for platform-server', () => {
|
||||
const mock = new MockServiceWorkerContainer();
|
||||
const comm = new NgswCommChannel(mock as any, 'server');
|
||||
expect(comm.isEnabled).toEqual(false);
|
||||
});
|
||||
describe('ngswCommChannelFactory', () => {
|
||||
it('gives disabled NgswCommChannel for platform-server', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: PLATFORM_ID, useValue: 'server'},
|
||||
{provide: RegistrationOptions, useValue: {enabled: true}}, {
|
||||
provide: NgswCommChannel,
|
||||
useFactory: ngswCommChannelFactory,
|
||||
deps: [RegistrationOptions, PLATFORM_ID]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
expect(TestBed.get(NgswCommChannel).isEnabled).toEqual(false);
|
||||
});
|
||||
it('gives disabled NgswCommChannel when \'enabled\' option is false', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: PLATFORM_ID, useValue: 'browser'},
|
||||
{provide: RegistrationOptions, useValue: {enabled: false}}, {
|
||||
provide: NgswCommChannel,
|
||||
useFactory: ngswCommChannelFactory,
|
||||
deps: [RegistrationOptions, PLATFORM_ID]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
expect(TestBed.get(NgswCommChannel).isEnabled).toEqual(false);
|
||||
});
|
||||
it('gives disabled NgswCommChannel when navigator.serviceWorker is undefined', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: PLATFORM_ID, useValue: 'browser'},
|
||||
{provide: RegistrationOptions, useValue: {enabled: true}},
|
||||
{
|
||||
provide: NgswCommChannel,
|
||||
useFactory: ngswCommChannelFactory,
|
||||
deps: [RegistrationOptions, PLATFORM_ID],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const context: any = global || window;
|
||||
const originalDescriptor = Object.getOwnPropertyDescriptor(context, 'navigator');
|
||||
const patchedDescriptor = {value: {serviceWorker: undefined}, configurable: true};
|
||||
|
||||
try {
|
||||
// Set `navigator` to `{serviceWorker: undefined}`.
|
||||
Object.defineProperty(context, 'navigator', patchedDescriptor);
|
||||
expect(TestBed.get(NgswCommChannel).isEnabled).toBe(false);
|
||||
} finally {
|
||||
if (originalDescriptor) {
|
||||
Object.defineProperty(context, 'navigator', originalDescriptor);
|
||||
} else {
|
||||
delete context.navigator;
|
||||
}
|
||||
}
|
||||
});
|
||||
it('gives enabled NgswCommChannel when browser supports SW and enabled option is true',
|
||||
() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: PLATFORM_ID, useValue: 'browser'},
|
||||
{provide: RegistrationOptions, useValue: {enabled: true}}, {
|
||||
provide: NgswCommChannel,
|
||||
useFactory: ngswCommChannelFactory,
|
||||
deps: [RegistrationOptions, PLATFORM_ID]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const context: any = global || window;
|
||||
const originalDescriptor = Object.getOwnPropertyDescriptor(context, 'navigator');
|
||||
const patchedDescriptor = {value: {serviceWorker: mock}, configurable: true};
|
||||
|
||||
try {
|
||||
// Set `navigator` to `{serviceWorker: mock}`.
|
||||
Object.defineProperty(context, 'navigator', patchedDescriptor);
|
||||
expect(TestBed.get(NgswCommChannel).isEnabled).toBe(true);
|
||||
} finally {
|
||||
if (originalDescriptor) {
|
||||
Object.defineProperty(context, 'navigator', originalDescriptor);
|
||||
} else {
|
||||
delete context.navigator;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
describe('SwPush', () => {
|
||||
let push: SwPush;
|
||||
@ -76,7 +161,7 @@ import {MockServiceWorkerContainer, MockServiceWorkerRegistration} from '../test
|
||||
expect(() => TestBed.get(SwPush)).not.toThrow();
|
||||
});
|
||||
describe('with no SW', () => {
|
||||
beforeEach(() => { comm = new NgswCommChannel(undefined, 'browser'); });
|
||||
beforeEach(() => { comm = new NgswCommChannel(undefined); });
|
||||
it('can be instantiated', () => { push = new SwPush(comm); });
|
||||
it('does not crash on subscription to observables', () => {
|
||||
push = new SwPush(comm);
|
||||
@ -170,7 +255,7 @@ import {MockServiceWorkerContainer, MockServiceWorkerRegistration} from '../test
|
||||
expect(() => TestBed.get(SwUpdate)).not.toThrow();
|
||||
});
|
||||
describe('with no SW', () => {
|
||||
beforeEach(() => { comm = new NgswCommChannel(undefined, 'browser'); });
|
||||
beforeEach(() => { comm = new NgswCommChannel(undefined); });
|
||||
it('can be instantiated', () => { update = new SwUpdate(comm); });
|
||||
it('does not crash on subscription to observables', () => {
|
||||
update = new SwUpdate(comm);
|
||||
|
@ -80,7 +80,7 @@ const serverUpdate =
|
||||
async_beforeEach(async() => {
|
||||
// Fire up the client.
|
||||
mock = new MockServiceWorkerContainer();
|
||||
comm = new NgswCommChannel(mock as any, 'browser');
|
||||
comm = new NgswCommChannel(mock as any);
|
||||
scope = new SwTestHarnessBuilder().withServerState(server).build();
|
||||
driver = new Driver(scope, scope, new CacheDatabase(scope, scope));
|
||||
|
||||
|
@ -79,12 +79,16 @@ def ts_web_test_suite(bootstrap = [], deps = [], **kwargs):
|
||||
_ts_web_test_suite(
|
||||
bootstrap = bootstrap,
|
||||
deps = local_deps,
|
||||
# Run unit tests on Chromium and Firefox by default.
|
||||
# Run unit tests on local Chromium by default.
|
||||
# You can exclude tests based on tags, e.g. to skip Firefox testing,
|
||||
# `bazel test --test_tag_filters=-browser:firefox-local [targets]`
|
||||
browsers = [
|
||||
"@io_bazel_rules_webtesting//browsers:chromium-local",
|
||||
"@io_bazel_rules_webtesting//browsers:firefox-local",
|
||||
# Don't test on local Firefox by default, for faster builds.
|
||||
# We think that bugs in Angular tend to be caught the same in any
|
||||
# evergreen browser.
|
||||
# "@io_bazel_rules_webtesting//browsers:firefox-local",
|
||||
# TODO(alexeagle): add remote browsers on SauceLabs
|
||||
],
|
||||
**kwargs)
|
||||
|
||||
|