Compare commits
38 Commits
9.0.0-rc.8
...
5.1.1
Author | SHA1 | Date | |
---|---|---|---|
e3140ae888 | |||
ca815106c9 | |||
d6da7988c0 | |||
41e1951ffb | |||
c02f97ce4e | |||
be9a7371b8 | |||
1f469497da | |||
8a5f0f7a64 | |||
8bcb093bfa | |||
abc3a1e844 | |||
9fbf850897 | |||
0c9f7b032a | |||
8b21be5da3 | |||
0a9a16183f | |||
28555bc1e7 | |||
d09d4971b3 | |||
f8a4d14c8f | |||
d713225128 | |||
5d3af4cad4 | |||
a7fe063aa5 | |||
affa54ddf9 | |||
02782c10ea | |||
8e5a3a42d6 | |||
dbef8ff2b0 | |||
c0f08be3fb | |||
f56cbcc1e5 | |||
1b86570b60 | |||
923227dec2 | |||
53b9de300b | |||
da587cb9ef | |||
e6a28054d8 | |||
69ed916b42 | |||
c3e8731145 | |||
501f01e9ac | |||
baeec4dbe2 | |||
160a154553 | |||
9dd60a5fb0 | |||
672733608b |
@ -7,17 +7,25 @@
|
||||
# To validate changes, use an online parser, eg.
|
||||
# http://yaml-online-parser.appspot.com/
|
||||
|
||||
# Variables
|
||||
|
||||
## IMPORTANT
|
||||
# If you change the `docker_image` version, also change the `cache_key` suffix and the version of
|
||||
# `com_github_bazelbuild_buildtools` in the `/WORKSPACE` file.
|
||||
var_1: &docker_image angular/ngcontainer:0.0.8
|
||||
var_2: &cache_key angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-0.0.8
|
||||
|
||||
# Settings common to each job
|
||||
anchor_1: &job_defaults
|
||||
working_directory: ~/ng
|
||||
docker:
|
||||
- image: angular/ngcontainer:0.0.6
|
||||
- image: *docker_image
|
||||
|
||||
# After checkout, rebase on top of master.
|
||||
# Similar to travis behavior, but not quite the same.
|
||||
# See https://discuss.circleci.com/t/1662
|
||||
anchor_2: &post_checkout
|
||||
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
|
||||
post: git pull --ff-only origin "refs/pull/${CIRCLE_PULL_REQUEST//*pull\//}/merge"
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
@ -26,8 +34,13 @@ jobs:
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
# Check BUILD.bazel formatting before we have a node_modules directory
|
||||
# Then we don't need any exclude pattern to avoid checking those files
|
||||
- run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) ||
|
||||
(echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)'
|
||||
|
||||
- restore_cache:
|
||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
key: *cache_key
|
||||
|
||||
- run: yarn install --frozen-lockfile --non-interactive
|
||||
- run: ./node_modules/.bin/gulp lint
|
||||
@ -38,13 +51,13 @@ jobs:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- restore_cache:
|
||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
key: *cache_key
|
||||
- run: bazel info release
|
||||
- run: bazel run @yarn//:yarn
|
||||
- run: bazel build packages/...
|
||||
- run: bazel test @angular//...
|
||||
- run: bazel build --config=ci packages/...
|
||||
- run: bazel test --config=ci packages/... @angular//...
|
||||
- save_cache:
|
||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
key: *cache_key
|
||||
paths:
|
||||
- "node_modules"
|
||||
|
||||
|
@ -44,6 +44,7 @@ groups:
|
||||
include:
|
||||
- "*"
|
||||
exclude:
|
||||
- ".circleci/*"
|
||||
- "aio/*"
|
||||
- "integration/*"
|
||||
- "modules/*"
|
||||
@ -73,6 +74,7 @@ groups:
|
||||
users:
|
||||
- alexeagle #primary
|
||||
- chuckjaz
|
||||
- IgorMinar
|
||||
- vikerman #fallback
|
||||
|
||||
build-and-ci:
|
||||
|
15
BUILD.bazel
15
BUILD.bazel
@ -1,4 +1,5 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(["tsconfig.json"])
|
||||
|
||||
# This rule belongs in node_modules/BUILD
|
||||
@ -11,17 +12,25 @@ filegroup(
|
||||
# bazel query "deps(:node_modules)" | wc -l
|
||||
# This won't scale in the general case.
|
||||
# TODO(alexeagle): figure out what to do
|
||||
srcs = glob(["/".join(["node_modules", pkg, "**", ext]) for pkg in [
|
||||
srcs = glob(["/".join([
|
||||
"node_modules",
|
||||
pkg,
|
||||
"**",
|
||||
ext,
|
||||
]) for pkg in [
|
||||
"jasmine",
|
||||
"typescript",
|
||||
"zone.js",
|
||||
"rxjs",
|
||||
"@types",
|
||||
"tsutils",
|
||||
"@types/jasmine",
|
||||
"@types/node",
|
||||
"@types/source-map",
|
||||
"tsickle",
|
||||
"hammerjs",
|
||||
"protobufjs",
|
||||
"bytebuffer",
|
||||
"reflect-metadata",
|
||||
"source-map-support",
|
||||
"minimist",
|
||||
] for ext in [
|
||||
"*.js",
|
||||
|
19
CHANGELOG.md
19
CHANGELOG.md
@ -1,3 +1,22 @@
|
||||
<a name="5.1.1"></a>
|
||||
## [5.1.1](https://github.com/angular/angular/compare/5.1.0...5.1.1) (2017-12-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animations:** ensure multi-level route leave animations are queryable ([#20787](https://github.com/angular/angular/issues/20787)) ([d09d497](https://github.com/angular/angular/commit/d09d497)), closes [#19807](https://github.com/angular/angular/issues/19807)
|
||||
* **animations:** ensure the web-animations driver properly handles empty keyframes ([#20648](https://github.com/angular/angular/issues/20648)) ([c3e8731](https://github.com/angular/angular/commit/c3e8731)), closes [#15858](https://github.com/angular/angular/issues/15858)
|
||||
* **animations:** properly recover and cleanup DOM when CD failures occur ([#20719](https://github.com/angular/angular/issues/20719)) ([e6a2805](https://github.com/angular/angular/commit/e6a2805)), closes [#19093](https://github.com/angular/angular/issues/19093)
|
||||
* **animations:** support webkit-based vendor prefixes for prop validations ([#19055](https://github.com/angular/angular/issues/19055)) ([501f01e](https://github.com/angular/angular/commit/501f01e)), closes [#18921](https://github.com/angular/angular/issues/18921)
|
||||
* **bazel:** don't equate moduleName with fileName ([#20895](https://github.com/angular/angular/issues/20895)) ([0c9f7b0](https://github.com/angular/angular/commit/0c9f7b0))
|
||||
* **compiler:** support referencing enums in namespaces ([#20947](https://github.com/angular/angular/issues/20947)) ([d6da798](https://github.com/angular/angular/commit/d6da798)), closes [#18170](https://github.com/angular/angular/issues/18170)
|
||||
* **compiler-cli:** disable checkTypes in emit. ([#20828](https://github.com/angular/angular/issues/20828)) ([160a154](https://github.com/angular/angular/commit/160a154))
|
||||
* **compiler-cli:** fix swallowed Error messages ([#20846](https://github.com/angular/angular/issues/20846)) ([6727336](https://github.com/angular/angular/commit/6727336))
|
||||
* **compiler-cli:** merge [@fileoverview](https://github.com/fileoverview) comments. ([#20870](https://github.com/angular/angular/issues/20870)) ([be9a737](https://github.com/angular/angular/commit/be9a737))
|
||||
* **router:** NavigatonError and NavigationCancel should be emitted after resetting the URL ([#20803](https://github.com/angular/angular/issues/20803)) ([baeec4d](https://github.com/angular/angular/commit/baeec4d))
|
||||
|
||||
|
||||
|
||||
<a name="5.1.0"></a>
|
||||
# [5.1.0](https://github.com/angular/angular/compare/5.1.0-rc.1...5.1.0) (2017-12-06)
|
||||
|
||||
|
40
WORKSPACE
40
WORKSPACE
@ -5,19 +5,51 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
git_repository(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
||||
commit = "0.2.1",
|
||||
tag = "0.3.1",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||
|
||||
check_bazel_version("0.8.1")
|
||||
node_repositories(package_json = ["//:package.json"])
|
||||
|
||||
local_repository(
|
||||
git_repository(
|
||||
name = "build_bazel_rules_typescript",
|
||||
path = "node_modules/@bazel/typescript",
|
||||
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
||||
tag = "0.6.0",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_repositories")
|
||||
|
||||
ts_repositories()
|
||||
|
||||
local_repository(
|
||||
name = "angular",
|
||||
path = "packages/bazel",
|
||||
)
|
||||
|
||||
local_repository(
|
||||
name = "rxjs",
|
||||
path = "node_modules/rxjs/src",
|
||||
)
|
||||
|
||||
git_repository(
|
||||
name = "com_github_bazelbuild_buildtools",
|
||||
remote = "https://github.com/bazelbuild/buildtools.git",
|
||||
# Note, this commit matches the version of buildifier in angular/ngcontainer
|
||||
# If you change this, also check if it matches the version in the angular/ngcontainer
|
||||
# version in /.circleci/config.yml
|
||||
commit = "b3b620e8bcff18ed3378cd3f35ebeb7016d71f71",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
url = "https://github.com/bazelbuild/rules_go/releases/download/0.7.1/rules_go-0.7.1.tar.gz",
|
||||
sha256 = "341d5eacef704415386974bc82a1783a8b7ffbff2ab6ba02375e1ca20d9b031c",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains()
|
||||
|
@ -100,7 +100,7 @@ locale data itself.
|
||||
If you want to register the imported locale data with another locale id, use the second parameter to
|
||||
specify a custom locale id. For example, Angular's locale data defines the locale id for French as
|
||||
"fr". You can use the second parameter to associate the imported French locale data with the custom
|
||||
locale id "fr-FR instead of "fr".
|
||||
locale id "fr-FR" instead of "fr".
|
||||
|
||||
The files in `@angular/common/locales` contain most of the locale data that you
|
||||
need, but some advanced formatting options might only be available in the extra dataset that you can
|
||||
|
@ -56,7 +56,7 @@
|
||||
"~~check-env": "node scripts/check-environment",
|
||||
"~~build": "ng build --target=production --environment=stable -sm",
|
||||
"post~~build": "yarn sw-manifest && yarn sw-copy",
|
||||
"~~update-webdriver": "webdriver-manager update --standalone false --gecko false"
|
||||
"~~update-webdriver": "webdriver-manager update --standalone false --gecko false $CHROMEDRIVER_VERSION_ARG"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.1 <9.0.0",
|
||||
@ -64,31 +64,31 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^5.0.0",
|
||||
"@angular/cdk": "^2.0.0-beta.12",
|
||||
"@angular/common": "^5.0.0",
|
||||
"@angular/compiler": "^5.0.0",
|
||||
"@angular/core": "^5.0.0-rc.9",
|
||||
"@angular/forms": "^5.0.0",
|
||||
"@angular/http": "^5.0.0",
|
||||
"@angular/material": "^2.0.0-beta.12",
|
||||
"@angular/platform-browser": "^5.0.0",
|
||||
"@angular/platform-browser-dynamic": "^5.0.0",
|
||||
"@angular/platform-server": "^5.0.0",
|
||||
"@angular/router": "^5.0.0",
|
||||
"@angular/animations": "^5.1.0-beta.2",
|
||||
"@angular/cdk": "^5.0.0-rc.1",
|
||||
"@angular/common": "^5.1.0-beta.2",
|
||||
"@angular/compiler": "^5.1.0-beta.2",
|
||||
"@angular/core": "^5.1.0-beta.2",
|
||||
"@angular/forms": "^5.1.0-beta.2",
|
||||
"@angular/http": "^5.1.0-beta.2",
|
||||
"@angular/material": "^5.0.0-rc.1",
|
||||
"@angular/platform-browser": "^5.1.0-beta.2",
|
||||
"@angular/platform-browser-dynamic": "^5.1.0-beta.2",
|
||||
"@angular/platform-server": "^5.1.0-beta.2",
|
||||
"@angular/router": "^5.1.0-beta.2",
|
||||
"@angular/service-worker": "^1.0.0-beta.16",
|
||||
"classlist.js": "^1.1.20150312",
|
||||
"core-js": "^2.4.1",
|
||||
"jasmine": "^2.6.0",
|
||||
"ng-pwa-tools": "^0.0.10",
|
||||
"rxjs": "^5.5.0",
|
||||
"rxjs": "^5.5.2",
|
||||
"tslib": "^1.7.1",
|
||||
"web-animations-js": "^2.2.5",
|
||||
"zone.js": "0.8.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "^1.5.0",
|
||||
"@angular/compiler-cli": "^5.0.0",
|
||||
"@angular/cli": "^1.6.0-rc.0",
|
||||
"@angular/compiler-cli": "^5.1.0-beta.2",
|
||||
"@types/jasmine": "^2.5.52",
|
||||
"@types/jasminewd2": "^2.0.3",
|
||||
"@types/node": "~6.0.60",
|
||||
@ -113,7 +113,7 @@
|
||||
"http-server": "^0.9.0",
|
||||
"ignore": "^3.3.3",
|
||||
"image-size": "^0.5.1",
|
||||
"jasmine-core": "^2.6.4",
|
||||
"jasmine-core": "^2.8.0",
|
||||
"jasmine-spec-reporter": "^4.1.0",
|
||||
"jsdom": "^9.12.0",
|
||||
"karma": "^1.7.0",
|
||||
|
@ -2,19 +2,19 @@
|
||||
"aio": {
|
||||
"master": {
|
||||
"gzip7": {
|
||||
"inline": 925,
|
||||
"main": 119519,
|
||||
"polyfills": 11863
|
||||
"inline": 941,
|
||||
"main": 116124,
|
||||
"polyfills": 11860
|
||||
},
|
||||
"gzip9": {
|
||||
"inline": 925,
|
||||
"main": 119301,
|
||||
"polyfills": 11861
|
||||
"inline": 941,
|
||||
"main": 115954,
|
||||
"polyfills": 11858
|
||||
},
|
||||
"uncompressed": {
|
||||
"inline": 1533,
|
||||
"main": 486493,
|
||||
"polyfills": 37068
|
||||
"inline": 1558,
|
||||
"main": 456432,
|
||||
"polyfills": 37070
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
<section class="sidenav-content" [id]="pageId" role="content">
|
||||
<aio-mode-banner [mode]="deployment.mode" [version]="versionInfo"></aio-mode-banner>
|
||||
<aio-doc-viewer [doc]="currentDocument" (docRendered)="onDocRendered()"></aio-doc-viewer>
|
||||
<aio-doc-viewer [doc]="currentDocument" (docReady)="onDocReady()" (docRemoved)="onDocRemoved()" (docInserted)="onDocInserted()"></aio-doc-viewer>
|
||||
<aio-dt [on]="dtOn" [(doc)]="currentDocument"></aio-dt>
|
||||
</section>
|
||||
|
||||
|
@ -6,12 +6,14 @@ import { HttpClient } from '@angular/common/http';
|
||||
import { MatProgressBar, MatSidenav } from '@angular/material';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppModule } from './app.module';
|
||||
import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';
|
||||
import { Deployment } from 'app/shared/deployment.service';
|
||||
import { EmbedComponentsService } from 'app/embed-components/embed-components.service';
|
||||
import { GaService } from 'app/shared/ga.service';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
@ -24,7 +26,7 @@ import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
|
||||
import { SearchResultsComponent } from 'app/shared/search-results/search-results.component';
|
||||
import { SearchService } from 'app/search/search.service';
|
||||
import { SelectComponent } from 'app/shared/select/select.component';
|
||||
import { TocComponent } from 'app/embedded/toc/toc.component';
|
||||
import { TocComponent } from 'app/layout/toc/toc.component';
|
||||
import { TocItem, TocService } from 'app/shared/toc.service';
|
||||
|
||||
const sideBySideBreakPoint = 992;
|
||||
@ -55,13 +57,18 @@ describe('AppComponent', () => {
|
||||
tocService = de.injector.get(TocService);
|
||||
};
|
||||
|
||||
|
||||
describe('with proper DocViewer', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
DocViewerComponent.animationsEnabled = false;
|
||||
|
||||
createTestingModule('a/b');
|
||||
initializeTest();
|
||||
});
|
||||
|
||||
afterEach(() => DocViewerComponent.animationsEnabled = true);
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeDefined();
|
||||
});
|
||||
@ -246,25 +253,25 @@ describe('AppComponent', () => {
|
||||
const sidenavBackdrop = fixture.debugElement.query(By.css('.mat-drawer-backdrop')).nativeElement;
|
||||
sidenavBackdrop.click();
|
||||
fixture.detectChanges();
|
||||
expect(sidenav.opened).toBe(false);
|
||||
expect(sidenav.opened).toBe(false);
|
||||
});
|
||||
|
||||
it('should close when nav to another guide page', () => {
|
||||
locationService.go('guide/bags');
|
||||
fixture.detectChanges();
|
||||
expect(sidenav.opened).toBe(false);
|
||||
expect(sidenav.opened).toBe(false);
|
||||
});
|
||||
|
||||
it('should close when nav to api page', () => {
|
||||
locationService.go('api');
|
||||
fixture.detectChanges();
|
||||
expect(sidenav.opened).toBe(false);
|
||||
expect(sidenav.opened).toBe(false);
|
||||
});
|
||||
|
||||
it('should close again when nav to market page', () => {
|
||||
locationService.go('features');
|
||||
fixture.detectChanges();
|
||||
expect(sidenav.opened).toBe(false);
|
||||
expect(sidenav.opened).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
@ -375,20 +382,27 @@ describe('AppComponent', () => {
|
||||
checkHostClass('view', '');
|
||||
});
|
||||
|
||||
it('should set the css class of the host container based on the open/closed state of the side nav', () => {
|
||||
it('should set the css class of the host container based on the open/closed state of the side nav', async () => {
|
||||
locationService.go('guide/pipes');
|
||||
fixture.detectChanges();
|
||||
checkHostClass('sidenav', 'open');
|
||||
|
||||
sidenav.close();
|
||||
sidenav.onClose.next();
|
||||
await waitForEmit(sidenav.onClose);
|
||||
fixture.detectChanges();
|
||||
checkHostClass('sidenav', 'closed');
|
||||
|
||||
sidenav.open();
|
||||
sidenav.onOpen.next();
|
||||
await waitForEmit(sidenav.onOpen);
|
||||
fixture.detectChanges();
|
||||
checkHostClass('sidenav', 'open');
|
||||
|
||||
function waitForEmit(emitter: Observable<void>): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
emitter.subscribe(resolve);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('should set the css class of the host container based on the initial deployment mode', () => {
|
||||
@ -407,7 +421,6 @@ describe('AppComponent', () => {
|
||||
});
|
||||
|
||||
describe('currentDocument', () => {
|
||||
|
||||
it('should display a guide page (guide/pipes)', () => {
|
||||
locationService.go('guide/pipes');
|
||||
fixture.detectChanges();
|
||||
@ -447,16 +460,19 @@ describe('AppComponent', () => {
|
||||
const scrollDelay = 500;
|
||||
let scrollService: ScrollService;
|
||||
let scrollSpy: jasmine.Spy;
|
||||
let scrollToTopSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
scrollService = fixture.debugElement.injector.get(ScrollService);
|
||||
scrollSpy = spyOn(scrollService, 'scroll');
|
||||
scrollToTopSpy = spyOn(scrollService, 'scrollToTop');
|
||||
});
|
||||
|
||||
it('should not scroll immediately when the docId (path) changes', () => {
|
||||
locationService.go('guide/pipes');
|
||||
// deliberately not calling `fixture.detectChanges` because don't want `onDocRendered`
|
||||
// deliberately not calling `fixture.detectChanges` because don't want `onDocInserted`
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
expect(scrollToTopSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should scroll when just the hash changes (# alone)', () => {
|
||||
@ -486,7 +502,7 @@ describe('AppComponent', () => {
|
||||
expect(scrollSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should scroll when e-nav to the empty path', () => {
|
||||
it('should scroll when re-nav to the empty path', () => {
|
||||
locationService.go('');
|
||||
scrollSpy.calls.reset();
|
||||
|
||||
@ -494,17 +510,29 @@ describe('AppComponent', () => {
|
||||
expect(scrollSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should scroll after a delay when call onDocRendered directly', fakeAsync(() => {
|
||||
component.onDocRendered();
|
||||
it('should scroll to top when call `onDocRemoved` directly', () => {
|
||||
scrollToTopSpy.calls.reset();
|
||||
|
||||
component.onDocRemoved();
|
||||
expect(scrollToTopSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should scroll after a delay when call `onDocInserted` directly', fakeAsync(() => {
|
||||
component.onDocInserted();
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should scroll (via onDocRendered) when finish navigating to a new doc', fakeAsync(() => {
|
||||
it('should scroll (via `onDocInserted`) when finish navigating to a new doc', fakeAsync(() => {
|
||||
expect(scrollToTopSpy).not.toHaveBeenCalled();
|
||||
|
||||
locationService.go('guide/pipes');
|
||||
fixture.detectChanges(); // triggers the event that calls onDocRendered
|
||||
fixture.detectChanges(); // triggers the event that calls `onDocInserted`
|
||||
expect(scrollToTopSpy).toHaveBeenCalled();
|
||||
expect(scrollSpy).not.toHaveBeenCalled();
|
||||
|
||||
tick(scrollDelay);
|
||||
expect(scrollSpy).toHaveBeenCalled();
|
||||
}));
|
||||
@ -867,7 +895,7 @@ describe('AppComponent', () => {
|
||||
|
||||
describe('with mocked DocViewer', () => {
|
||||
const getDocViewer = () => fixture.debugElement.query(By.css('aio-doc-viewer'));
|
||||
const triggerDocRendered = () => getDocViewer().triggerEventHandler('docRendered', {});
|
||||
const triggerDocReady = () => getDocViewer().triggerEventHandler('docReady', undefined);
|
||||
|
||||
beforeEach(() => {
|
||||
createTestingModule('a/b');
|
||||
@ -879,7 +907,7 @@ describe('AppComponent', () => {
|
||||
});
|
||||
|
||||
describe('initial rendering', () => {
|
||||
it('should initially add the starting class until the first document is rendered', fakeAsync(() => {
|
||||
it('should initially add the starting class until the first document is ready', fakeAsync(() => {
|
||||
const getSidenavContainer = () => fixture.debugElement.query(By.css('mat-sidenav-container'));
|
||||
|
||||
initializeTest();
|
||||
@ -887,7 +915,7 @@ describe('AppComponent', () => {
|
||||
expect(component.isStarting).toBe(true);
|
||||
expect(getSidenavContainer().classes['starting']).toBe(true);
|
||||
|
||||
triggerDocRendered();
|
||||
triggerDocReady();
|
||||
fixture.detectChanges();
|
||||
expect(component.isStarting).toBe(true);
|
||||
expect(getSidenavContainer().classes['starting']).toBe(true);
|
||||
@ -910,7 +938,7 @@ describe('AppComponent', () => {
|
||||
const getProgressBar = () => fixture.debugElement.query(By.directive(MatProgressBar));
|
||||
const initializeAndCompleteNavigation = () => {
|
||||
initializeTest();
|
||||
triggerDocRendered();
|
||||
triggerDocReady();
|
||||
tick(HIDE_DELAY);
|
||||
};
|
||||
|
||||
@ -947,7 +975,7 @@ describe('AppComponent', () => {
|
||||
it('should not be shown when re-navigating to the empty path', fakeAsync(() => {
|
||||
initializeAndCompleteNavigation();
|
||||
locationService.urlSubject.next('');
|
||||
triggerDocRendered();
|
||||
triggerDocReady();
|
||||
|
||||
locationService.urlSubject.next('');
|
||||
|
||||
@ -958,12 +986,12 @@ describe('AppComponent', () => {
|
||||
tick(HIDE_DELAY); // Fire the remaining timer or `fakeAsync()` complains.
|
||||
}));
|
||||
|
||||
it('should not be shown if the doc is rendered quickly', fakeAsync(() => {
|
||||
it('should not be shown if the doc is prepared quickly', fakeAsync(() => {
|
||||
initializeAndCompleteNavigation();
|
||||
locationService.urlSubject.next('c/d');
|
||||
|
||||
tick(SHOW_DELAY - 1);
|
||||
triggerDocRendered();
|
||||
triggerDocReady();
|
||||
|
||||
tick(1);
|
||||
fixture.detectChanges();
|
||||
@ -972,12 +1000,12 @@ describe('AppComponent', () => {
|
||||
tick(HIDE_DELAY); // Fire the remaining timer or `fakeAsync()` complains.
|
||||
}));
|
||||
|
||||
it('should be shown if rendering the doc takes too long', fakeAsync(() => {
|
||||
it('should be shown if preparing the doc takes too long', fakeAsync(() => {
|
||||
initializeAndCompleteNavigation();
|
||||
locationService.urlSubject.next('c/d');
|
||||
|
||||
tick(SHOW_DELAY);
|
||||
triggerDocRendered();
|
||||
triggerDocReady();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getProgressBar()).toBeTruthy();
|
||||
@ -985,12 +1013,12 @@ describe('AppComponent', () => {
|
||||
tick(HIDE_DELAY); // Fire the remaining timer or `fakeAsync()` complains.
|
||||
}));
|
||||
|
||||
it('should be hidden (after a delay) once the doc is rendered', fakeAsync(() => {
|
||||
it('should be hidden (after a delay) once the doc has been prepared', fakeAsync(() => {
|
||||
initializeAndCompleteNavigation();
|
||||
locationService.urlSubject.next('c/d');
|
||||
|
||||
tick(SHOW_DELAY);
|
||||
triggerDocRendered();
|
||||
triggerDocReady();
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getProgressBar()).toBeTruthy();
|
||||
@ -1007,10 +1035,10 @@ describe('AppComponent', () => {
|
||||
it('should only take the latest request into account', fakeAsync(() => {
|
||||
initializeAndCompleteNavigation();
|
||||
locationService.urlSubject.next('c/d'); // The URL changes.
|
||||
locationService.urlSubject.next('e/f'); // The URL changes again before `onDocRendered()`.
|
||||
locationService.urlSubject.next('e/f'); // The URL changes again before `onDocReady()`.
|
||||
|
||||
tick(SHOW_DELAY - 1); // `onDocRendered()` is triggered (for the last doc),
|
||||
triggerDocRendered(); // before the progress bar is shown.
|
||||
tick(SHOW_DELAY - 1); // `onDocReady()` is triggered (for the last doc),
|
||||
triggerDocReady(); // before the progress bar is shown.
|
||||
|
||||
tick(1);
|
||||
fixture.detectChanges();
|
||||
@ -1033,6 +1061,7 @@ function createTestingModule(initialUrl: string, mode: string = 'stable') {
|
||||
imports: [ AppModule ],
|
||||
providers: [
|
||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||
{ provide: EmbedComponentsService, useClass: TestEmbedComponentsService },
|
||||
{ provide: GaService, useClass: TestGaService },
|
||||
{ provide: HttpClient, useClass: TestHttpClient },
|
||||
{ provide: LocationService, useFactory: () => mockLocationService },
|
||||
@ -1047,6 +1076,10 @@ function createTestingModule(initialUrl: string, mode: string = 'stable') {
|
||||
});
|
||||
}
|
||||
|
||||
class TestEmbedComponentsService {
|
||||
embedInto = jasmine.createSpy('embedInto').and.returnValue(of([]));
|
||||
}
|
||||
|
||||
class TestGaService {
|
||||
locationChanged = jasmine.createSpy('locationChanged');
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component, ElementRef, HostBinding, HostListener, OnInit,
|
||||
QueryList, ViewChild, ViewChildren } from '@angular/core';
|
||||
import { MatSidenav } from '@angular/material';
|
||||
import { MatSidenav } from '@angular/material/sidenav';
|
||||
|
||||
import { CurrentNodes, NavigationService, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';
|
||||
import { DocumentService, DocumentContents } from 'app/documents/document.service';
|
||||
@ -203,22 +203,29 @@ export class AppComponent implements OnInit {
|
||||
this.scrollService.scroll();
|
||||
}
|
||||
|
||||
onDocRendered() {
|
||||
onDocReady() {
|
||||
// Stop fetching timeout (which, when render is fast, means progress bar never shown)
|
||||
clearTimeout(this.isFetchingTimeout);
|
||||
|
||||
// Put page in a clean visual state
|
||||
this.scrollService.scrollToTop();
|
||||
|
||||
// Scroll 500ms after the doc-viewer has finished rendering the new doc
|
||||
// The delay is to allow time for async layout to complete
|
||||
// If progress bar has been shown, keep it for at least 500ms (to avoid flashing).
|
||||
setTimeout(() => {
|
||||
this.autoScroll();
|
||||
this.isStarting = false;
|
||||
this.isFetching = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
onDocRemoved() {
|
||||
// The previous document has been removed.
|
||||
// Scroll to top to restore a clean visual state for the new document.
|
||||
this.scrollService.scrollToTop();
|
||||
}
|
||||
|
||||
onDocInserted() {
|
||||
// Scroll 500ms after the new document has been inserted into the doc-viewer.
|
||||
// The delay is to allow time for async layout to complete.
|
||||
setTimeout(() => this.autoScroll(), 500);
|
||||
}
|
||||
|
||||
onDocVersionChange(versionIndex: number) {
|
||||
const version = this.docVersions[versionIndex];
|
||||
if (version.url) {
|
||||
@ -291,7 +298,7 @@ export class AppComponent implements OnInit {
|
||||
const el = this.hostElement.nativeElement as Element;
|
||||
this.tocMaxHeightOffset =
|
||||
el.querySelector('footer').clientHeight +
|
||||
el.querySelector('mat-toolbar.app-toolbar').clientHeight +
|
||||
el.querySelector('.app-toolbar').clientHeight +
|
||||
24; // fudge margin
|
||||
}
|
||||
|
||||
|
48
aio/src/app/app.module.spec.ts
Normal file
48
aio/src/app/app.module.spec.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AppModule } from 'app/app.module';
|
||||
import { ComponentsOrModulePath, EMBEDDED_COMPONENTS } from 'app/embed-components/embed-components.service';
|
||||
import { embeddedComponents } from 'app/embedded/embedded.module';
|
||||
|
||||
describe('AppModule', () => {
|
||||
let componentsMap: {[multiSelectorstring: string]: ComponentsOrModulePath};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({imports: [AppModule]});
|
||||
componentsMap = TestBed.get(EMBEDDED_COMPONENTS);
|
||||
});
|
||||
|
||||
it('should provide a map of selectors to embedded components (or module)', () => {
|
||||
const allSelectors = Object.keys(componentsMap);
|
||||
|
||||
expect(allSelectors.length).toBeGreaterThan(1);
|
||||
allSelectors.forEach(selector => {
|
||||
const value = componentsMap[selector];
|
||||
const isArrayOrString = Array.isArray(value) || (typeof value === 'string');
|
||||
expect(isArrayOrString).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should provide a list of eagerly-loaded embedded components', () => {
|
||||
const eagerSelector = Object.keys(componentsMap).find(selector => Array.isArray(componentsMap[selector]));
|
||||
const selectorCount = eagerSelector.split(',').length;
|
||||
|
||||
expect(eagerSelector).not.toBeNull();
|
||||
expect(selectorCount).toBe(componentsMap[eagerSelector].length);
|
||||
|
||||
// For example...
|
||||
expect(eagerSelector).toContain('aio-toc');
|
||||
});
|
||||
|
||||
it('should provide a list of lazy-loaded embedded components', () => {
|
||||
const lazySelector = Object.keys(componentsMap).find(selector => selector.includes('code-example'));
|
||||
const selectorCount = lazySelector.split(',').length;
|
||||
|
||||
expect(lazySelector).not.toBeNull();
|
||||
expect(selectorCount).toBe(embeddedComponents.length);
|
||||
|
||||
// For example...
|
||||
expect(lazySelector).toContain('code-example');
|
||||
expect(lazySelector).toContain('code-tabs');
|
||||
expect(lazySelector).toContain('live-example');
|
||||
});
|
||||
});
|
@ -5,36 +5,22 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common';
|
||||
|
||||
import {
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatIconRegistry,
|
||||
MatInputModule,
|
||||
MatProgressBarModule,
|
||||
MatSidenavModule,
|
||||
MatTabsModule,
|
||||
MatToolbarModule
|
||||
} from '@angular/material';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
|
||||
import {
|
||||
Platform
|
||||
} from '@angular/cdk/platform';
|
||||
import { ROUTES } from '@angular/router';
|
||||
|
||||
|
||||
// Temporary fix for MatSidenavModule issue:
|
||||
// crashes with "missing first" operator when SideNav.mode is "over"
|
||||
import 'rxjs/add/operator/first';
|
||||
|
||||
import { SwUpdatesModule } from 'app/sw-updates/sw-updates.module';
|
||||
|
||||
import { AppComponent } from 'app/app.component';
|
||||
import { ApiService } from 'app/embedded/api/api.service';
|
||||
import { EMBEDDED_COMPONENTS, EmbeddedComponentsMap } from 'app/embed-components/embed-components.service';
|
||||
import { CustomIconRegistry, SVG_ICONS } from 'app/shared/custom-icon-registry';
|
||||
import { Deployment } from 'app/shared/deployment.service';
|
||||
import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';
|
||||
import { DtComponent } from 'app/layout/doc-viewer/dt.component';
|
||||
import { ModeBannerComponent } from 'app/layout/mode-banner/mode-banner.component';
|
||||
import { EmbeddedModule } from 'app/embedded/embedded.module';
|
||||
import { GaService } from 'app/shared/ga.service';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
@ -47,11 +33,18 @@ import { NavMenuComponent } from 'app/layout/nav-menu/nav-menu.component';
|
||||
import { NavItemComponent } from 'app/layout/nav-item/nav-item.component';
|
||||
import { ScrollService } from 'app/shared/scroll.service';
|
||||
import { ScrollSpyService } from 'app/shared/scroll-spy.service';
|
||||
import { SearchBoxComponent } from './search/search-box/search-box.component';
|
||||
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
|
||||
import { TocComponent } from 'app/layout/toc/toc.component';
|
||||
import { TocService } from 'app/shared/toc.service';
|
||||
import { WindowToken, windowProvider } from 'app/shared/window';
|
||||
|
||||
import { EmbedComponentsModule } from 'app/embed-components/embed-components.module';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
import { SwUpdatesModule } from 'app/sw-updates/sw-updates.module';
|
||||
|
||||
|
||||
// The path to the `EmbeddedModule`.
|
||||
const embeddedModulePath = 'app/embedded/embedded.module#EmbeddedModule';
|
||||
|
||||
// These are the hardcoded inline svg sources to be used by the `<mat-icon>` component
|
||||
export const svgIconProviders = [
|
||||
@ -78,15 +71,13 @@ export const svgIconProviders = [
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
EmbeddedModule,
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
EmbedComponentsModule,
|
||||
HttpClientModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatProgressBarModule,
|
||||
MatSidenavModule,
|
||||
MatTabsModule,
|
||||
MatToolbarModule,
|
||||
SwUpdatesModule,
|
||||
SharedModule
|
||||
@ -100,10 +91,10 @@ export const svgIconProviders = [
|
||||
NavMenuComponent,
|
||||
NavItemComponent,
|
||||
SearchBoxComponent,
|
||||
TocComponent,
|
||||
TopMenuComponent,
|
||||
],
|
||||
providers: [
|
||||
ApiService,
|
||||
Deployment,
|
||||
DocumentService,
|
||||
GaService,
|
||||
@ -113,15 +104,32 @@ export const svgIconProviders = [
|
||||
LocationService,
|
||||
{ provide: MatIconRegistry, useClass: CustomIconRegistry },
|
||||
NavigationService,
|
||||
Platform,
|
||||
ScrollService,
|
||||
ScrollSpyService,
|
||||
SearchService,
|
||||
svgIconProviders,
|
||||
TocService,
|
||||
{ provide: WindowToken, useFactory: windowProvider },
|
||||
|
||||
{
|
||||
provide: EMBEDDED_COMPONENTS,
|
||||
useValue: {
|
||||
/* tslint:disable: max-line-length */
|
||||
'aio-toc': [TocComponent],
|
||||
'aio-api-list, aio-contributor-list, aio-file-not-found-search, aio-resource-list, code-example, code-tabs, current-location, live-example': embeddedModulePath,
|
||||
/* tslint:enable: max-line-length */
|
||||
} as EmbeddedComponentsMap,
|
||||
},
|
||||
{
|
||||
// This is currently the only way to get `@angular/cli`
|
||||
// to split `EmbeddedModule` into a separate chunk :(
|
||||
provide: ROUTES,
|
||||
useValue: [{ path: '/embedded', loadChildren: embeddedModulePath }],
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
entryComponents: [ TocComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
13
aio/src/app/embed-components/embed-components.module.ts
Normal file
13
aio/src/app/embed-components/embed-components.module.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { NgModule, NgModuleFactoryLoader, SystemJsNgModuleLoader } from '@angular/core';
|
||||
|
||||
import { EmbedComponentsService } from './embed-components.service';
|
||||
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
EmbedComponentsService,
|
||||
{ provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader },
|
||||
],
|
||||
})
|
||||
export class EmbedComponentsModule {
|
||||
}
|
378
aio/src/app/embed-components/embed-components.service.spec.ts
Normal file
378
aio/src/app/embed-components/embed-components.service.spec.ts
Normal file
@ -0,0 +1,378 @@
|
||||
import { ComponentFactory, ComponentFactoryResolver, ComponentRef, NgModuleFactoryLoader } from '@angular/core';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import {
|
||||
MockNgModuleFactoryLoader, TestEmbedComponentsService, TestModule, mockEmbeddedModulePath,
|
||||
testEagerEmbeddedComponents, testEagerEmbeddedSelectors, testLazyEmbeddedComponents
|
||||
} from 'testing/embed-components-utils';
|
||||
import { EmbedComponentsService, ComponentsOrModulePath } from './embed-components.service';
|
||||
|
||||
|
||||
describe('EmbedComponentsService', () => {
|
||||
let service: TestEmbedComponentsService;
|
||||
let host: HTMLElement;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({imports: [TestModule]});
|
||||
|
||||
service = TestBed.get(EmbedComponentsService);
|
||||
host = document.createElement('div');
|
||||
});
|
||||
|
||||
it('should be instantiated', () => {
|
||||
expect(service).toEqual(jasmine.any(EmbedComponentsService));
|
||||
});
|
||||
|
||||
describe('#createComponentFactories()', () => {
|
||||
let factories: typeof service.componentFactories;
|
||||
let resolver: ComponentFactoryResolver;
|
||||
|
||||
const doCreateComponentFactories = () =>
|
||||
service.createComponentFactories(testEagerEmbeddedComponents, resolver);
|
||||
|
||||
beforeEach(() => {
|
||||
factories = service.componentFactories;
|
||||
resolver = TestBed.get(ComponentFactoryResolver) as ComponentFactoryResolver;
|
||||
});
|
||||
|
||||
it('should create a factory entry for each component', () => {
|
||||
expect(factories.size).toBe(0);
|
||||
|
||||
doCreateComponentFactories();
|
||||
expect(factories.size).toBe(testEagerEmbeddedComponents.length);
|
||||
});
|
||||
|
||||
it('should key the factory entries by selector', () => {
|
||||
doCreateComponentFactories();
|
||||
|
||||
const actualSelectors = Array.from(factories.keys());
|
||||
const expectedSelectors = testEagerEmbeddedSelectors;
|
||||
|
||||
expect(actualSelectors).toEqual(expectedSelectors);
|
||||
});
|
||||
|
||||
it('should store the projected content property name', () => {
|
||||
doCreateComponentFactories();
|
||||
|
||||
const actualContentPropNames = Array.from(factories.values()).map(x => x.contentPropertyName);
|
||||
const expectedContentPropNames = testEagerEmbeddedSelectors.map(x => service.selectorToContentPropertyName(x));
|
||||
|
||||
expect(actualContentPropNames).toEqual(expectedContentPropNames);
|
||||
});
|
||||
|
||||
it('should store the factory for each component', () => {
|
||||
doCreateComponentFactories();
|
||||
|
||||
const actualFactories = Array.from(factories.values()).map(x => x.factory);
|
||||
const expectedComponentTypes = testEagerEmbeddedComponents;
|
||||
|
||||
actualFactories.forEach((factory, i) => {
|
||||
expect(factory).toEqual(jasmine.any(ComponentFactory));
|
||||
expect(factory.componentType).toBe(expectedComponentTypes[i]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createComponents()', () => {
|
||||
const FooComponent = testEagerEmbeddedComponents[0];
|
||||
const BarComponent = testEagerEmbeddedComponents[1];
|
||||
|
||||
beforeEach(() => service.prepareComponentFactories(testEagerEmbeddedComponents));
|
||||
|
||||
it('should apply all embedded components (and return the `ComponentRef`s)', () => {
|
||||
host.innerHTML = `
|
||||
<p>Header</p>
|
||||
<p><aio-eager-foo></aio-eager-foo></p>
|
||||
<p><aio-eager-bar></aio-eager-bar></p>
|
||||
<p>Footer</p>
|
||||
`;
|
||||
|
||||
const componentRefs = service.createComponents(host);
|
||||
|
||||
expect(host.innerHTML).toContain('Foo Component');
|
||||
expect(host.innerHTML).toContain('Bar Component');
|
||||
|
||||
expect(componentRefs.length).toBe(2);
|
||||
expect(componentRefs[0].instance).toEqual(jasmine.any(FooComponent));
|
||||
expect(componentRefs[1].instance).toEqual(jasmine.any(BarComponent));
|
||||
});
|
||||
|
||||
it('should apply embedded components to all matching elements', () => {
|
||||
host.innerHTML = `
|
||||
<p>Header</p>
|
||||
<p><aio-eager-foo></aio-eager-foo></p>
|
||||
<p><aio-eager-bar></aio-eager-bar></p>
|
||||
<p><aio-eager-foo></aio-eager-foo></p>
|
||||
<p><aio-eager-bar></aio-eager-bar></p>
|
||||
<p>Footer</p>
|
||||
`;
|
||||
|
||||
const componentRefs = service.createComponents(host);
|
||||
|
||||
expect(componentRefs.length).toBe(4);
|
||||
expect(componentRefs[0].instance).toEqual(jasmine.any(FooComponent));
|
||||
expect(componentRefs[1].instance).toEqual(jasmine.any(FooComponent));
|
||||
expect(componentRefs[2].instance).toEqual(jasmine.any(BarComponent));
|
||||
expect(componentRefs[3].instance).toEqual(jasmine.any(BarComponent));
|
||||
});
|
||||
|
||||
it('should allow projecting content by assigning it on the element', () => {
|
||||
const projectedContent = 'Projected content';
|
||||
host.innerHTML = `
|
||||
<p>Header</p>
|
||||
<p><aio-eager-bar>${projectedContent}</aio-eager-bar></p>
|
||||
<p>Footer</p>
|
||||
`;
|
||||
|
||||
const componentRefs = service.createComponents(host);
|
||||
componentRefs[0].changeDetectorRef.detectChanges();
|
||||
|
||||
const barEl = host.querySelector('aio-eager-bar');
|
||||
|
||||
expect(barEl['aioEagerBarContent']).toBe(projectedContent);
|
||||
expect(barEl.innerHTML).toContain(projectedContent);
|
||||
});
|
||||
|
||||
// Because `FooComponent` is processed before `BarComponent`...
|
||||
it('should apply `FooComponent` within `BarComponent`', () => {
|
||||
host.innerHTML = `
|
||||
<aio-eager-bar>
|
||||
<aio-eager-foo></aio-eager-foo>
|
||||
</aio-eager-bar>
|
||||
`;
|
||||
|
||||
const componentRefs = service.createComponents(host);
|
||||
componentRefs.forEach(ref => ref.changeDetectorRef.detectChanges());
|
||||
|
||||
expect(host.innerHTML).toContain('Foo Component');
|
||||
expect(host.innerHTML).toContain('Bar Component');
|
||||
|
||||
expect(componentRefs.length).toBe(2);
|
||||
expect(componentRefs[0].instance).toEqual(jasmine.any(FooComponent));
|
||||
expect(componentRefs[1].instance).toEqual(jasmine.any(BarComponent));
|
||||
});
|
||||
|
||||
// Because `BarComponent` is processed after `FooComponent`...
|
||||
it('should not apply `BarComponent` within `FooComponent`', () => {
|
||||
host.innerHTML = `
|
||||
<aio-eager-foo>
|
||||
<aio-eager-bar></aio-eager-bar>
|
||||
</aio-eager-foo>
|
||||
`;
|
||||
|
||||
const componentRefs = service.createComponents(host);
|
||||
componentRefs.forEach(ref => ref.changeDetectorRef.detectChanges());
|
||||
|
||||
expect(host.innerHTML).toContain('Foo Component');
|
||||
expect(host.innerHTML).not.toContain('Bar Component');
|
||||
|
||||
expect(componentRefs.length).toBe(1);
|
||||
expect(componentRefs[0].instance).toEqual(jasmine.any(FooComponent));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#embedInto()', () => {
|
||||
let mockComponentRefs: ComponentRef<any>[];
|
||||
let createComponentsSpy: jasmine.Spy;
|
||||
let prepareComponentFactoriesSpy: jasmine.Spy;
|
||||
|
||||
const doEmbed = (contents: string) =>
|
||||
new Promise<ComponentRef<any>[]>((resolve, reject) => {
|
||||
host.innerHTML = contents;
|
||||
service.embedInto(host).subscribe(resolve, reject);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
mockComponentRefs = [{foo: true}, {bar: true}] as any as ComponentRef<any>[];
|
||||
|
||||
createComponentsSpy = spyOn(service, 'createComponents').and.returnValue(mockComponentRefs);
|
||||
prepareComponentFactoriesSpy = spyOn(service, 'prepareComponentFactories')
|
||||
.and.returnValue(Promise.resolve());
|
||||
});
|
||||
|
||||
it('should return an observable', done => {
|
||||
service.embedInto(host).subscribe(done, done.fail);
|
||||
});
|
||||
|
||||
describe('(preparing component factories)', () => {
|
||||
it('should return an array of `ComponentRef`s', async () => {
|
||||
// When there are embedded components.
|
||||
expect(await doEmbed('<aio-eager-foo></aio-eager-foo>')).toEqual(mockComponentRefs);
|
||||
expect(await doEmbed('<aio-lazy-bar></aio-lazy-bar>')).toEqual(mockComponentRefs);
|
||||
|
||||
// When there are no embedded components.
|
||||
expect(await doEmbed('<div>Test</div>')).toEqual([]);
|
||||
expect(await doEmbed('')).toEqual([]);
|
||||
});
|
||||
|
||||
it('should prepare all component factories if there are embedded components', async () => {
|
||||
await doEmbed(`
|
||||
<div><aio-eager-foo><b>foo</b></aio-eager-foo></div>
|
||||
<span><aio-lazy-foo><i>bar</i></aio-lazy-foo></span>
|
||||
`);
|
||||
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledTimes(2);
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledWith(testEagerEmbeddedComponents);
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledWith(mockEmbeddedModulePath);
|
||||
});
|
||||
|
||||
it('should only prepare the necessary factories', async () => {
|
||||
await doEmbed('<aio-eager-foo>Eager only</aio-eager-foo>');
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledTimes(1);
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledWith(testEagerEmbeddedComponents);
|
||||
|
||||
await doEmbed('<aio-lazy-foo>Lazy only</aio-lazy-foo>');
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledTimes(2);
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledWith(mockEmbeddedModulePath);
|
||||
});
|
||||
|
||||
it('should not load embedded components if the document does not contain any', async () => {
|
||||
await doEmbed('');
|
||||
await doEmbed('<no-aio-eager-foo></no-aio-eager-foo>');
|
||||
await doEmbed('<no-aio-lazy-foo></no-aio-lazy-foo>');
|
||||
|
||||
expect(prepareComponentFactoriesSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('(creating embedded components)', () => {
|
||||
it('should create embedded components if the element contains any', async () => {
|
||||
await doEmbed('<div><aio-eager-foo><i>blah</i></aio-eager-foo></div>');
|
||||
|
||||
expect(createComponentsSpy).toHaveBeenCalledTimes(1);
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledBefore(createComponentsSpy);
|
||||
|
||||
prepareComponentFactoriesSpy.calls.reset();
|
||||
createComponentsSpy.calls.reset();
|
||||
|
||||
await doEmbed('<aio-lazy-bar><i>blah</i></aio-lazy-bar>');
|
||||
expect(createComponentsSpy).toHaveBeenCalledTimes(1);
|
||||
expect(prepareComponentFactoriesSpy).toHaveBeenCalledBefore(createComponentsSpy);
|
||||
});
|
||||
|
||||
it('should emit the created embedded components', async () => {
|
||||
const componentRefs = await doEmbed('<aio-eager-foo></aio-eager-foo>');
|
||||
expect(componentRefs).toBe(mockComponentRefs);
|
||||
});
|
||||
|
||||
it('should not create embedded components if the element does not contain any', async () => {
|
||||
await doEmbed(`
|
||||
<aio-eager-foo-not></aio-eager-foo-not>
|
||||
<aio-lazy-bar></aio-lazy-bar>
|
||||
`);
|
||||
expect(createComponentsSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not create embedded components if the document is empty', async () => {
|
||||
await doEmbed('');
|
||||
expect(createComponentsSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not create embedded components if unsubscribed from', async () => {
|
||||
const preparePromise = Promise.resolve();
|
||||
prepareComponentFactoriesSpy.and.returnValue(preparePromise);
|
||||
|
||||
// When not unsubscribed from...
|
||||
host.innerHTML = '<aio-eager-foo></aio-eager-foo>';
|
||||
service.embedInto(host).subscribe();
|
||||
await new Promise(resolve => setTimeout(resolve));
|
||||
expect(createComponentsSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
createComponentsSpy.calls.reset();
|
||||
|
||||
// When unsubscribed from...
|
||||
host.innerHTML = '<aio-eager-foo></aio-eager-foo>';
|
||||
service.embedInto(host).subscribe().unsubscribe();
|
||||
await new Promise(resolve => setTimeout(resolve));
|
||||
expect(createComponentsSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#prepareComponentFactories()', () => {
|
||||
let loader: MockNgModuleFactoryLoader;
|
||||
let resolver: ComponentFactoryResolver;
|
||||
let createComponentFactoriesSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
loader = TestBed.get(NgModuleFactoryLoader);
|
||||
resolver = TestBed.get(ComponentFactoryResolver);
|
||||
|
||||
createComponentFactoriesSpy = spyOn(service, 'createComponentFactories');
|
||||
});
|
||||
|
||||
[testLazyEmbeddedComponents, mockEmbeddedModulePath].forEach((compsOrPath: ComponentsOrModulePath) => {
|
||||
const useComponents = Array.isArray(compsOrPath);
|
||||
|
||||
describe(`(using ${useComponents ? 'component types' : 'module path'})`, () => {
|
||||
const doPrepareComponentFactories = () =>
|
||||
service.prepareComponentFactories(compsOrPath);
|
||||
|
||||
it('should return a promise', done => {
|
||||
doPrepareComponentFactories().then(done, done.fail);
|
||||
});
|
||||
|
||||
it('should create the component factories', async () => {
|
||||
expect(createComponentFactoriesSpy).not.toHaveBeenCalled();
|
||||
|
||||
await doPrepareComponentFactories();
|
||||
expect(createComponentFactoriesSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
const args = createComponentFactoriesSpy.calls.mostRecent().args;
|
||||
expect(args[0]).toBe(testLazyEmbeddedComponents);
|
||||
|
||||
if (useComponents) {
|
||||
expect(args[1]).toBe(resolver);
|
||||
} else {
|
||||
expect(args[1]).not.toBe(resolver);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not create create the component factories more than once', async () => {
|
||||
const results = await Promise.all([
|
||||
doPrepareComponentFactories(),
|
||||
doPrepareComponentFactories(),
|
||||
]);
|
||||
|
||||
expect(createComponentFactoriesSpy).toHaveBeenCalledTimes(1);
|
||||
expect(results[1]).toBe(results[0]);
|
||||
|
||||
const anotherResult = await doPrepareComponentFactories();
|
||||
|
||||
expect(createComponentFactoriesSpy).toHaveBeenCalledTimes(1);
|
||||
expect(anotherResult).toBe(results[0]);
|
||||
});
|
||||
|
||||
it(`should ${useComponents ? 'not load' : 'load'} the embedded module`, async () => {
|
||||
expect(loader.loadedPaths).toEqual([]);
|
||||
|
||||
await doPrepareComponentFactories();
|
||||
const expectedLoadedPaths = useComponents ? [] : [mockEmbeddedModulePath];
|
||||
|
||||
expect(loader.loadedPaths).toEqual(expectedLoadedPaths);
|
||||
});
|
||||
|
||||
it(`should not load the embedded module more than once`, async () => {
|
||||
await Promise.all([
|
||||
doPrepareComponentFactories(),
|
||||
doPrepareComponentFactories(),
|
||||
]);
|
||||
const loadedPathCount = loader.loadedPaths.length;
|
||||
|
||||
expect(loadedPathCount).toBeLessThan(2);
|
||||
|
||||
await doPrepareComponentFactories();
|
||||
|
||||
expect(loader.loadedPaths.length).toBe(loadedPathCount);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#selectorToContentPropertyName()', () => {
|
||||
it('should convert an element selector to a property name', () => {
|
||||
expect(service.selectorToContentPropertyName('foobar')).toBe('foobarContent');
|
||||
expect(service.selectorToContentPropertyName('baz-qux')).toBe('bazQuxContent');
|
||||
});
|
||||
});
|
||||
});
|
154
aio/src/app/embed-components/embed-components.service.ts
Normal file
154
aio/src/app/embed-components/embed-components.service.ts
Normal file
@ -0,0 +1,154 @@
|
||||
import {
|
||||
ComponentFactory, ComponentFactoryResolver, ComponentRef, Inject, Injectable, InjectionToken,
|
||||
Injector, NgModuleFactory, NgModuleFactoryLoader, Type
|
||||
} from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
|
||||
|
||||
export interface EmbeddedComponentFactory {
|
||||
contentPropertyName: string;
|
||||
factory: ComponentFactory<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A mapping from combined component selectors (keys) to the corresponding components (values). The
|
||||
* components can be specified either as a list of embedded components or a path to a module that
|
||||
* provides embedded components (i.e. implements `WithEmbeddedComponents`).
|
||||
*/
|
||||
export interface EmbeddedComponentsMap {
|
||||
[multiSelector: string]: ComponentsOrModulePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface expected to be implemented by all modules that contribute components to the
|
||||
* `EmbeddedComponentsMap`.
|
||||
*/
|
||||
export interface WithEmbeddedComponents {
|
||||
embeddedComponents: Type<any>[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Either an array of components or the path to a module that implements `WithEmbeddedComponents`.
|
||||
*/
|
||||
export type ComponentsOrModulePath = Type<any>[] | string;
|
||||
|
||||
/**
|
||||
* The injection token for the `EmbeddedComponentsMap`.
|
||||
*/
|
||||
export const EMBEDDED_COMPONENTS = new InjectionToken<EmbeddedComponentsMap>('EMBEDDED_COMPONENTS');
|
||||
|
||||
/**
|
||||
* Embed components into an element. It takes care of indentifying the embedded components, loading
|
||||
* the necessary modules and instantiating the components.
|
||||
*
|
||||
* Embeddable components are identified and loaded based on the info in `EmbeddedComponentsMap`
|
||||
* (provided through dependency injection).
|
||||
*
|
||||
* The caller is responsible for trigering change detection and destroying the components as
|
||||
* necessary.
|
||||
*/
|
||||
@Injectable()
|
||||
export class EmbedComponentsService {
|
||||
private componentFactoriesReady = new Map<ComponentsOrModulePath, Promise<void>>();
|
||||
protected componentFactories = new Map<string, EmbeddedComponentFactory>();
|
||||
|
||||
constructor(
|
||||
private injector: Injector,
|
||||
private loader: NgModuleFactoryLoader,
|
||||
private resolver: ComponentFactoryResolver,
|
||||
@Inject(EMBEDDED_COMPONENTS) private embeddedComponentsMap: EmbeddedComponentsMap) { }
|
||||
|
||||
/**
|
||||
* Embed components into the specified element:
|
||||
* - Load the necessary modules (if any).
|
||||
* - Prepare the component factories.
|
||||
* - Instantiate the components.
|
||||
*
|
||||
* Return the list of `ComponentRef`s.
|
||||
*/
|
||||
embedInto(elem: HTMLElement): Observable<ComponentRef<any>[]> {
|
||||
const requiredComponents = Object.keys(this.embeddedComponentsMap)
|
||||
.filter(selector => elem.querySelector(selector))
|
||||
.map(selector => this.embeddedComponentsMap[selector]);
|
||||
|
||||
const factoriesReady = requiredComponents.map(compsOrPath => this.prepareComponentFactories(compsOrPath));
|
||||
|
||||
return !requiredComponents.length
|
||||
? of([])
|
||||
: of(undefined)
|
||||
.switchMap(() => Promise.all(factoriesReady))
|
||||
.switchMap(() => [this.createComponents(elem)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the embedded component factories (which will later be used to instantiate components).
|
||||
*/
|
||||
protected createComponentFactories(components: Type<any>[], resolver: ComponentFactoryResolver): void {
|
||||
for (const comp of components) {
|
||||
const factory = resolver.resolveComponentFactory(comp);
|
||||
const selector = factory.selector;
|
||||
const contentPropertyName = this.selectorToContentPropertyName(selector);
|
||||
this.componentFactories.set(selector, {contentPropertyName, factory});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate embedded components for the current contents of `elem`.
|
||||
* (Store the original HTML contents of each element on the corresponding property for later
|
||||
* retrieval by the component instance.)
|
||||
*/
|
||||
protected createComponents(elem: HTMLElement): ComponentRef<any>[] {
|
||||
const componentRefs: ComponentRef<any>[] = [];
|
||||
|
||||
this.componentFactories.forEach(({contentPropertyName, factory}, selector) => {
|
||||
const componentHosts = elem.querySelectorAll(selector);
|
||||
|
||||
// Cast due to https://github.com/Microsoft/TypeScript/issues/4947.
|
||||
for (const host of componentHosts as any as HTMLElement[]) {
|
||||
// Hack: Preserve the current element content, because the factory will empty it out.
|
||||
// Security: The source of this `innerHTML` should always be authored by the documentation
|
||||
// team and is considered to be safe.
|
||||
host[contentPropertyName] = host.innerHTML;
|
||||
componentRefs.push(factory.create(this.injector, [], host));
|
||||
}
|
||||
});
|
||||
|
||||
return componentRefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the component factories for the given components.
|
||||
* If necessary, load and instantiate the module first.
|
||||
*/
|
||||
protected prepareComponentFactories(compsOrPath: ComponentsOrModulePath): Promise<void> {
|
||||
if (!this.componentFactoriesReady.has(compsOrPath)) {
|
||||
const componentsAndResolverPromise = (typeof compsOrPath !== 'string')
|
||||
? Promise.resolve({components: compsOrPath, resolver: this.resolver})
|
||||
: this.loader.load(compsOrPath).then((ngModuleFactory: NgModuleFactory<WithEmbeddedComponents>) => {
|
||||
const moduleRef = ngModuleFactory.create(this.injector);
|
||||
return {
|
||||
components: moduleRef.instance.embeddedComponents,
|
||||
resolver: moduleRef.componentFactoryResolver,
|
||||
};
|
||||
});
|
||||
|
||||
const readyPromise = componentsAndResolverPromise
|
||||
.then(({components, resolver}) => this.createComponentFactories(components, resolver));
|
||||
|
||||
this.componentFactoriesReady.set(compsOrPath, readyPromise);
|
||||
}
|
||||
|
||||
return this.componentFactoriesReady.get(compsOrPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the component content property name by converting the selector to camelCase and
|
||||
* appending `Content`, e.g. `live-example` => `liveExampleContent`.
|
||||
*/
|
||||
protected selectorToContentPropertyName(selector: string): string {
|
||||
return selector.replace(/-(.)/g, (match, $1) => $1.toUpperCase()) + 'Content';
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ import { Component, ElementRef, ViewChild, OnChanges, Input } from '@angular/cor
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
import { PrettyPrinter } from './pretty-printer.service';
|
||||
import { CopierService } from 'app/shared/copier.service';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
|
||||
const defaultLineNumsCount = 10; // by default, show linenums over this number
|
||||
|
||||
|
@ -1,20 +1,24 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgModule, Type } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { ContributorService } from './contributor/contributor.service';
|
||||
import { CopierService } from 'app/shared/copier.service';
|
||||
import { PrettyPrinter } from './code/pretty-printer.service';
|
||||
import { WithEmbeddedComponents } from 'app/embed-components/embed-components.service';
|
||||
|
||||
// Any components that we want to use inside embedded components must be declared or imported here
|
||||
// It is not enough just to import them inside the AppModule
|
||||
|
||||
// Reusable components (used inside embedded components)
|
||||
import { MatIconModule, MatSnackBarModule, MatTabsModule } from '@angular/material';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { CodeComponent } from './code/code.component';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
|
||||
// Embedded Components
|
||||
import { ApiListComponent } from './api/api-list.component';
|
||||
import { ApiService } from './api/api.service';
|
||||
import { CodeExampleComponent } from './code/code-example.component';
|
||||
import { CodeTabsComponent } from './code/code-tabs.component';
|
||||
import { ContributorListComponent } from './contributor/contributor-list.component';
|
||||
@ -24,22 +28,16 @@ import { FileNotFoundSearchComponent } from './search/file-not-found-search.comp
|
||||
import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/live-example.component';
|
||||
import { ResourceListComponent } from './resource/resource-list.component';
|
||||
import { ResourceService } from './resource/resource.service';
|
||||
import { TocComponent } from './toc/toc.component';
|
||||
|
||||
/** Components that can be embedded in docs
|
||||
/**
|
||||
* Components that can be embedded in docs,
|
||||
* such as CodeExampleComponent, LiveExampleComponent,...
|
||||
*/
|
||||
export const embeddedComponents: any[] = [
|
||||
export const embeddedComponents: Type<any>[] = [
|
||||
ApiListComponent, CodeExampleComponent, CodeTabsComponent, ContributorListComponent,
|
||||
CurrentLocationComponent, FileNotFoundSearchComponent, LiveExampleComponent, ResourceListComponent,
|
||||
TocComponent
|
||||
CurrentLocationComponent, FileNotFoundSearchComponent, LiveExampleComponent, ResourceListComponent
|
||||
];
|
||||
|
||||
/** Injectable class w/ property returning components that can be embedded in docs */
|
||||
export class EmbeddedComponents {
|
||||
components = embeddedComponents;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
@ -54,16 +52,15 @@ export class EmbeddedComponents {
|
||||
ContributorComponent,
|
||||
EmbeddedPlunkerComponent
|
||||
],
|
||||
exports: [
|
||||
TocComponent
|
||||
],
|
||||
providers: [
|
||||
ApiService,
|
||||
ContributorService,
|
||||
CopierService,
|
||||
EmbeddedComponents,
|
||||
PrettyPrinter,
|
||||
ResourceService
|
||||
],
|
||||
entryComponents: [ embeddedComponents ]
|
||||
})
|
||||
export class EmbeddedModule { }
|
||||
export class EmbeddedModule implements WithEmbeddedComponents {
|
||||
embeddedComponents = embeddedComponents;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,19 @@
|
||||
import {
|
||||
Component, ComponentFactory, ComponentFactoryResolver, ComponentRef,
|
||||
DoCheck, ElementRef, EventEmitter, Injector, Input, OnDestroy,
|
||||
Output
|
||||
} from '@angular/core';
|
||||
|
||||
import { EmbeddedComponents } from 'app/embedded/embedded.module';
|
||||
import { DocumentContents } from 'app/documents/document.service';
|
||||
import { Component, ComponentRef, DoCheck, ElementRef, EventEmitter, Input, OnDestroy, Output } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
import { timer } from 'rxjs/observable/timer';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/do';
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
import 'rxjs/add/operator/takeUntil';
|
||||
|
||||
import { DocumentContents } from 'app/documents/document.service';
|
||||
import { EmbedComponentsService } from 'app/embed-components/embed-components.service';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
import { TocService } from 'app/shared/toc.service';
|
||||
|
||||
interface EmbeddedComponentFactory {
|
||||
contentPropertyName: string;
|
||||
factory: ComponentFactory<any>;
|
||||
}
|
||||
|
||||
// Initialization prevents flicker once pre-rendering is on
|
||||
const initialDocViewerElement = document.querySelector('aio-doc-viewer');
|
||||
@ -25,19 +26,48 @@ const initialDocViewerContent = initialDocViewerElement ? initialDocViewerElemen
|
||||
// encapsulation: ViewEncapsulation.Native
|
||||
})
|
||||
export class DocViewerComponent implements DoCheck, OnDestroy {
|
||||
// Enable/Disable view transition animations.
|
||||
static animationsEnabled = true;
|
||||
|
||||
private embeddedComponents: ComponentRef<any>[] = [];
|
||||
private embeddedComponentFactories: Map<string, EmbeddedComponentFactory> = new Map();
|
||||
private hostElement: HTMLElement;
|
||||
|
||||
@Output()
|
||||
docRendered = new EventEmitter();
|
||||
private void$ = of<void>(undefined);
|
||||
private onDestroy$ = new EventEmitter<void>();
|
||||
private docContents$ = new EventEmitter<DocumentContents>();
|
||||
|
||||
protected embeddedComponentRefs: ComponentRef<any>[] = [];
|
||||
protected currViewContainer: HTMLElement = document.createElement('div');
|
||||
protected nextViewContainer: HTMLElement = document.createElement('div');
|
||||
|
||||
@Input()
|
||||
set doc(newDoc: DocumentContents) {
|
||||
// Ignore `undefined` values that could happen if the host component
|
||||
// does not initially specify a value for the `doc` input.
|
||||
if (newDoc) {
|
||||
this.docContents$.emit(newDoc);
|
||||
}
|
||||
}
|
||||
|
||||
// The new document is ready to be inserted into the viewer.
|
||||
// (Embedded components have been loaded and instantiated, if necessary.)
|
||||
@Output() docReady = new EventEmitter<void>();
|
||||
|
||||
// The previous document has been removed from the viewer.
|
||||
// (The leaving animation (if any) has been completed and the node has been removed from the DOM.)
|
||||
@Output() docRemoved = new EventEmitter<void>();
|
||||
|
||||
// The new document has been inserted into the viewer.
|
||||
// (The node has been inserted into the DOM, but the entering animation may still be in progress.)
|
||||
@Output() docInserted = new EventEmitter<void>();
|
||||
|
||||
// The new document has been fully rendered into the viewer.
|
||||
// (The entering animation has been completed.)
|
||||
@Output() docRendered = new EventEmitter<void>();
|
||||
|
||||
constructor(
|
||||
componentFactoryResolver: ComponentFactoryResolver,
|
||||
elementRef: ElementRef,
|
||||
embeddedComponents: EmbeddedComponents,
|
||||
private injector: Injector,
|
||||
private embedComponentsService: EmbedComponentsService,
|
||||
private logger: Logger,
|
||||
private titleService: Title,
|
||||
private tocService: TocService
|
||||
) {
|
||||
@ -45,84 +75,148 @@ export class DocViewerComponent implements DoCheck, OnDestroy {
|
||||
// Security: the initialDocViewerContent comes from the prerendered DOM and is considered to be secure
|
||||
this.hostElement.innerHTML = initialDocViewerContent;
|
||||
|
||||
for (const component of embeddedComponents.components) {
|
||||
const factory = componentFactoryResolver.resolveComponentFactory(component);
|
||||
const selector = factory.selector;
|
||||
const contentPropertyName = this.selectorToContentPropertyName(selector);
|
||||
this.embeddedComponentFactories.set(selector, { contentPropertyName, factory });
|
||||
}
|
||||
}
|
||||
|
||||
@Input()
|
||||
set doc(newDoc: DocumentContents) {
|
||||
this.ngOnDestroy();
|
||||
if (newDoc) {
|
||||
this.build(newDoc);
|
||||
this.docRendered.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add doc content to host element and build it out with embedded components
|
||||
*/
|
||||
private build(doc: DocumentContents) {
|
||||
|
||||
// security: the doc.content is always authored by the documentation team
|
||||
// and is considered to be safe
|
||||
this.hostElement.innerHTML = doc.contents || '';
|
||||
|
||||
if (!doc.contents) { return; }
|
||||
|
||||
this.addTitleAndToc(doc.id);
|
||||
|
||||
// TODO(i): why can't I use for-of? why doesn't typescript like Map#value() iterators?
|
||||
this.embeddedComponentFactories.forEach(({ contentPropertyName, factory }, selector) => {
|
||||
const embeddedComponentElements = this.hostElement.querySelectorAll(selector);
|
||||
|
||||
// cast due to https://github.com/Microsoft/TypeScript/issues/4947
|
||||
for (const element of embeddedComponentElements as any as HTMLElement[]){
|
||||
// hack: preserve the current element content because the factory will empty it out
|
||||
// security: the source of this innerHTML is always authored by the documentation team
|
||||
// and is considered to be safe
|
||||
element[contentPropertyName] = element.innerHTML;
|
||||
this.embeddedComponents.push(factory.create(this.injector, [], element));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private addTitleAndToc(docId: string) {
|
||||
this.tocService.reset();
|
||||
const titleEl = this.hostElement.querySelector('h1');
|
||||
let title = '';
|
||||
|
||||
// Only create TOC for docs with an <h1> title
|
||||
// If you don't want a TOC, add "no-toc" class to <h1>
|
||||
if (titleEl) {
|
||||
title = (typeof titleEl.innerText === 'string') ? titleEl.innerText : titleEl.textContent;
|
||||
if (!/(no-toc|notoc)/i.test(titleEl.className)) {
|
||||
this.tocService.genToc(this.hostElement, docId);
|
||||
titleEl.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
|
||||
}
|
||||
if (this.hostElement.firstElementChild) {
|
||||
this.currViewContainer = this.hostElement.firstElementChild as HTMLElement;
|
||||
} else {
|
||||
this.hostElement.appendChild(this.currViewContainer);
|
||||
}
|
||||
|
||||
this.titleService.setTitle(title ? `Angular - ${title}` : 'Angular');
|
||||
this.onDestroy$.subscribe(() => this.destroyEmbeddedComponents());
|
||||
this.docContents$
|
||||
.switchMap(newDoc => this.render(newDoc))
|
||||
.takeUntil(this.onDestroy$)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
ngDoCheck() {
|
||||
this.embeddedComponents.forEach(comp => comp.changeDetectorRef.detectChanges());
|
||||
this.embeddedComponentRefs.forEach(comp => comp.changeDetectorRef.detectChanges());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
// destroy these components else there will be memory leaks
|
||||
this.embeddedComponents.forEach(comp => comp.destroy());
|
||||
this.embeddedComponents.length = 0;
|
||||
this.onDestroy$.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the component content property name by converting the selector to camelCase and appending
|
||||
* 'Content', e.g. live-example => liveExampleContent
|
||||
* Destroy the embedded components to avoid memory leaks.
|
||||
*/
|
||||
private selectorToContentPropertyName(selector: string) {
|
||||
return selector.replace(/-(.)/g, (match, $1) => $1.toUpperCase()) + 'Content';
|
||||
protected destroyEmbeddedComponents(): void {
|
||||
this.embeddedComponentRefs.forEach(comp => comp.destroy());
|
||||
this.embeddedComponentRefs = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare for setting the window title and ToC.
|
||||
* Return a function to actually set them.
|
||||
*/
|
||||
protected prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void {
|
||||
const titleEl = targetElem.querySelector('h1');
|
||||
const hasToc = !!titleEl && !/no-?toc/i.test(titleEl.className);
|
||||
|
||||
if (hasToc) {
|
||||
titleEl.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
|
||||
}
|
||||
|
||||
return () => {
|
||||
this.tocService.reset();
|
||||
let title = '';
|
||||
|
||||
// Only create ToC for docs with an `<h1>` heading.
|
||||
// If you don't want a ToC, add "no-toc" class to `<h1>`.
|
||||
if (titleEl) {
|
||||
title = (typeof titleEl.innerText === 'string') ? titleEl.innerText : titleEl.textContent;
|
||||
|
||||
if (hasToc) {
|
||||
this.tocService.genToc(targetElem, docId);
|
||||
}
|
||||
}
|
||||
|
||||
this.titleService.setTitle(title ? `Angular - ${title}` : 'Angular');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add doc content to host element and build it out with embedded components.
|
||||
*/
|
||||
protected render(doc: DocumentContents): Observable<void> {
|
||||
let addTitleAndToc: () => void;
|
||||
|
||||
return this.void$
|
||||
// Security: `doc.contents` is always authored by the documentation team
|
||||
// and is considered to be safe.
|
||||
.do(() => this.nextViewContainer.innerHTML = doc.contents || '')
|
||||
.do(() => addTitleAndToc = this.prepareTitleAndToc(this.nextViewContainer, doc.id))
|
||||
.switchMap(() => this.embedComponentsService.embedInto(this.nextViewContainer))
|
||||
.do(() => this.docReady.emit())
|
||||
.do(() => this.destroyEmbeddedComponents())
|
||||
.do(componentRefs => this.embeddedComponentRefs = componentRefs)
|
||||
.switchMap(() => this.swapViews(addTitleAndToc))
|
||||
.do(() => this.docRendered.emit())
|
||||
.catch(err => {
|
||||
this.nextViewContainer.innerHTML = '';
|
||||
this.logger.error(`[DocViewer]: Error preparing document '${doc.id}'.`, err);
|
||||
return this.void$;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the views, removing `currViewContainer` and inserting `nextViewContainer`.
|
||||
* (At this point all content should be ready, including having loaded and instantiated embedded
|
||||
* components.)
|
||||
*
|
||||
* Optionally, run a callback as soon as `nextViewContainer` has been inserted, but before the
|
||||
* entering animation has been completed. This is useful for work that needs to be done as soon as
|
||||
* the element has been attached to the DOM.
|
||||
*/
|
||||
protected swapViews(onInsertedCb = () => undefined): Observable<void> {
|
||||
const raf$ = new Observable<void>(subscriber => {
|
||||
const rafId = requestAnimationFrame(() => {
|
||||
subscriber.next();
|
||||
subscriber.complete();
|
||||
});
|
||||
return () => cancelAnimationFrame(rafId);
|
||||
});
|
||||
|
||||
const animateProp =
|
||||
(elem: HTMLElement, prop: string, from: string, to: string, duration = 333) => {
|
||||
elem.style.transition = '';
|
||||
return !DocViewerComponent.animationsEnabled
|
||||
? this.void$.do(() => elem.style[prop] = to)
|
||||
: this.void$
|
||||
// In order to ensure that the `from` value will be applied immediately (i.e.
|
||||
// without transition) and that the `to` value will be affected by the
|
||||
// `transition` style, we need to ensure an animation frame has passed between
|
||||
// setting each style.
|
||||
.switchMap(() => raf$).do(() => elem.style[prop] = from)
|
||||
.switchMap(() => raf$).do(() => elem.style.transition = `all ${duration}ms ease-in-out`)
|
||||
.switchMap(() => raf$).do(() => elem.style[prop] = to)
|
||||
.switchMap(() => timer(duration)).switchMap(() => this.void$);
|
||||
};
|
||||
|
||||
const animateLeave = (elem: HTMLElement) => animateProp(elem, 'opacity', '1', '0.25');
|
||||
const animateEnter = (elem: HTMLElement) => animateProp(elem, 'opacity', '0.25', '1');
|
||||
|
||||
let done$ = this.void$;
|
||||
|
||||
if (this.currViewContainer.parentElement) {
|
||||
done$ = done$
|
||||
// Remove the current view from the viewer.
|
||||
.switchMap(() => animateLeave(this.currViewContainer))
|
||||
.do(() => this.currViewContainer.parentElement.removeChild(this.currViewContainer))
|
||||
.do(() => this.docRemoved.emit());
|
||||
}
|
||||
|
||||
return done$
|
||||
// Insert the next view into the viewer.
|
||||
.do(() => this.hostElement.appendChild(this.nextViewContainer))
|
||||
.do(() => onInsertedCb())
|
||||
.do(() => this.docInserted.emit())
|
||||
.switchMap(() => animateEnter(this.nextViewContainer))
|
||||
// Update the view references and clean up unused nodes.
|
||||
.do(() => {
|
||||
const prevViewContainer = this.currViewContainer;
|
||||
this.currViewContainer = this.nextViewContainer;
|
||||
this.nextViewContainer = prevViewContainer;
|
||||
this.nextViewContainer.innerHTML = ''; // Empty to release memory.
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { InjectionToken, Inject, Injectable } from '@angular/core';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
import { MatIconRegistry } from '@angular/material';
|
||||
import { MatIconRegistry } from '@angular/material/icon';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
@ -27,19 +27,6 @@ interface SvgIconMap {
|
||||
[iconName: string]: SVGElement;
|
||||
}
|
||||
|
||||
// <hack-alert>
|
||||
// @angular/material's `MdIconRegitry` currently (v2.0.0-beta.8) requires an instance of `Http`
|
||||
// (from @angular/http). It is only used to [get some text content][1], so we can create a wrapper
|
||||
// around `HttpClient` and pretend it is `Http`.
|
||||
// [1]: https://github.com/angular/material2/blob/2.0.0-beta.8/src/lib/icon/icon-registry.ts#L465-L466
|
||||
// </hack-alert>
|
||||
function createFakeHttp(http: HttpClient): any {
|
||||
return {
|
||||
get: (url: string) => http.get(url, {responseType: 'text'})
|
||||
.map(data => ({text: () => data}))
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom replacement for Angular Material's `MdIconRegistry`, which allows
|
||||
* us to provide preloaded icon SVG sources.
|
||||
@ -49,7 +36,7 @@ export class CustomIconRegistry extends MatIconRegistry {
|
||||
private preloadedSvgElements: SvgIconMap = {};
|
||||
|
||||
constructor(http: HttpClient, sanitizer: DomSanitizer, @Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
|
||||
super(createFakeHttp(http), sanitizer);
|
||||
super(http, sanitizer);
|
||||
this.loadSvgElements(svgIcons);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ export class ScrollService {
|
||||
// at the top (e.g. toolbar) + some margin
|
||||
get topOffset() {
|
||||
if (!this._topOffset) {
|
||||
const toolbar = this.document.querySelector('mat-toolbar.app-toolbar');
|
||||
const toolbar = this.document.querySelector('.app-toolbar');
|
||||
this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
|
||||
}
|
||||
return this._topOffset;
|
||||
|
@ -100,7 +100,7 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mat-toolbar-row a {
|
||||
.app-toolbar a {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: white;
|
||||
|
88
aio/src/testing/doc-viewer-utils.ts
Normal file
88
aio/src/testing/doc-viewer-utils.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { Component, ComponentRef, NgModule, ViewChild } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { DocumentContents } from 'app/documents/document.service';
|
||||
import { EmbedComponentsService } from 'app/embed-components/embed-components.service';
|
||||
import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';
|
||||
import { Logger } from 'app/shared/logger.service';
|
||||
import { TocService } from 'app/shared/toc.service';
|
||||
import { MockLogger } from 'testing/logger.service';
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// `TestDocViewerComponent` (for exposing internal `DocViewerComponent` methods as public). ///
|
||||
/// Only used for type-casting; the actual implementation is irrelevant. ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export class TestDocViewerComponent extends DocViewerComponent {
|
||||
embeddedComponentRefs: ComponentRef<any>[];
|
||||
currViewContainer: HTMLElement;
|
||||
nextViewContainer: HTMLElement;
|
||||
|
||||
destroyEmbeddedComponents(): void { return null as any; }
|
||||
prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void { return null as any; }
|
||||
render(doc: DocumentContents): Observable<void> { return null as any; }
|
||||
swapViews(onInsertedCb?: () => void): Observable<void> { return null as any; }
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// `TestModule` and `TestParentComponent`. ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Test parent component.
|
||||
@Component({
|
||||
selector: 'aio-test',
|
||||
template: '<aio-doc-viewer [doc]="currentDoc">Test Component</aio-doc-viewer>',
|
||||
})
|
||||
export class TestParentComponent {
|
||||
currentDoc: DocumentContents;
|
||||
@ViewChild(DocViewerComponent) docViewer: DocViewerComponent;
|
||||
}
|
||||
|
||||
// Mock services.
|
||||
export class MockEmbedComponentsService {
|
||||
embedInto = jasmine.createSpy('EmbedComponentsService#embedInto');
|
||||
}
|
||||
|
||||
export class MockTitle {
|
||||
setTitle = jasmine.createSpy('Title#reset');
|
||||
}
|
||||
|
||||
export class MockTocService {
|
||||
genToc = jasmine.createSpy('TocService#genToc');
|
||||
reset = jasmine.createSpy('TocService#reset');
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DocViewerComponent,
|
||||
TestParentComponent,
|
||||
],
|
||||
providers: [
|
||||
{ provide: Logger, useClass: MockLogger },
|
||||
{ provide: EmbedComponentsService, useClass: MockEmbedComponentsService },
|
||||
{ provide: Title, useClass: MockTitle },
|
||||
{ provide: TocService, useClass: MockTocService },
|
||||
],
|
||||
})
|
||||
export class TestModule { }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// An observable with spies to test subscribing/unsubscribing. ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export class ObservableWithSubscriptionSpies<T = void> extends Observable<T> {
|
||||
unsubscribeSpies: jasmine.Spy[] = [];
|
||||
subscribeSpy = spyOn(this, 'subscribe').and.callFake((...args) => {
|
||||
const subscription = super.subscribe(...args);
|
||||
const unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough();
|
||||
this.unsubscribeSpies.push(unsubscribeSpy);
|
||||
return subscription;
|
||||
});
|
||||
|
||||
constructor(subscriber = () => undefined) { super(subscriber); }
|
||||
}
|
138
aio/src/testing/embed-components-utils.ts
Normal file
138
aio/src/testing/embed-components-utils.ts
Normal file
@ -0,0 +1,138 @@
|
||||
import {
|
||||
Component, ComponentFactoryResolver, ComponentRef, CompilerFactory, ElementRef, NgModule,
|
||||
NgModuleFactoryLoader, OnInit, Type, ViewChild, getPlatform
|
||||
} from '@angular/core';
|
||||
|
||||
import {
|
||||
ComponentsOrModulePath, EMBEDDED_COMPONENTS, EmbedComponentsService, EmbeddedComponentFactory,
|
||||
WithEmbeddedComponents
|
||||
} from 'app/embed-components/embed-components.service';
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// `TestEmbedComponentsService` (for exposing internal methods as public). ///
|
||||
/// Only used for type-casting; the actual implementation is irrelevant. ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export class TestEmbedComponentsService extends EmbedComponentsService {
|
||||
componentFactories: Map<string, EmbeddedComponentFactory>;
|
||||
|
||||
createComponentFactories(components: Type<any>[], resolver: ComponentFactoryResolver): void { return null as any; }
|
||||
createComponents(elem: HTMLElement): ComponentRef<any>[] { return null as any; }
|
||||
prepareComponentFactories(compsOrPath: ComponentsOrModulePath): Promise<void> { return null as any; }
|
||||
selectorToContentPropertyName(selector: string): string { return null as any; }
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Mock `EmbeddedModule` and test components. ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Test embedded components.
|
||||
@Component({
|
||||
selector: 'aio-eager-foo',
|
||||
template: `Eager Foo Component`,
|
||||
})
|
||||
class EagerFooComponent { }
|
||||
|
||||
@Component({
|
||||
selector: 'aio-eager-bar',
|
||||
template: `
|
||||
<hr>
|
||||
<h2>Eager Bar Component</h2>
|
||||
<p #content></p>
|
||||
<hr>
|
||||
`,
|
||||
})
|
||||
class EagerBarComponent implements OnInit {
|
||||
@ViewChild('content') contentRef: ElementRef;
|
||||
|
||||
constructor(public elementRef: ElementRef) { }
|
||||
|
||||
// Project content in `ngOnInit()` just like in `CodeExampleComponent`.
|
||||
ngOnInit() {
|
||||
// Security: This is a test component; never deployed.
|
||||
this.contentRef.nativeElement.innerHTML = this.elementRef.nativeElement.aioEagerBarContent;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'aio-lazy-foo',
|
||||
template: `Lazy Foo Component`,
|
||||
})
|
||||
class LazyFooComponent { }
|
||||
|
||||
@Component({
|
||||
selector: 'aio-lazy-bar',
|
||||
template: `
|
||||
<hr>
|
||||
<h2>Lazy Bar Component</h2>
|
||||
<p #content></p>
|
||||
<hr>
|
||||
`,
|
||||
})
|
||||
class LazyBarComponent implements OnInit {
|
||||
@ViewChild('content') contentRef: ElementRef;
|
||||
|
||||
constructor(public elementRef: ElementRef) { }
|
||||
|
||||
// Project content in `ngOnInit()` just like in `CodeExampleComponent`.
|
||||
ngOnInit() {
|
||||
// Security: This is a test component; never deployed.
|
||||
this.contentRef.nativeElement.innerHTML = this.elementRef.nativeElement.aioLazyBarContent;
|
||||
}
|
||||
}
|
||||
|
||||
// Export test embedded selectors and components.
|
||||
export const testEagerEmbeddedSelectors = ['aio-eager-foo', 'aio-eager-bar'];
|
||||
export const testEagerEmbeddedComponents = [EagerFooComponent, EagerBarComponent];
|
||||
export const testLazyEmbeddedSelectors = ['aio-lazy-foo', 'aio-lazy-bar'];
|
||||
export const testLazyEmbeddedComponents = [LazyFooComponent, LazyBarComponent];
|
||||
|
||||
// Export mock `EmbeddedModule` and path.
|
||||
export const mockEmbeddedModulePath = 'mock/mock-embedded#MockEmbeddedModule';
|
||||
|
||||
@NgModule({
|
||||
declarations: [testLazyEmbeddedComponents],
|
||||
entryComponents: [testLazyEmbeddedComponents],
|
||||
})
|
||||
class MockEmbeddedModule implements WithEmbeddedComponents {
|
||||
embeddedComponents = testLazyEmbeddedComponents;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// `TestModule`. ///
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Mock services.
|
||||
export class MockNgModuleFactoryLoader implements NgModuleFactoryLoader {
|
||||
loadedPaths: string[] = [];
|
||||
|
||||
load(path: string) {
|
||||
this.loadedPaths.push(path);
|
||||
|
||||
const platformRef = getPlatform();
|
||||
const compilerFactory = platformRef.injector.get(CompilerFactory) as CompilerFactory;
|
||||
const compiler = compilerFactory.createCompiler([]);
|
||||
|
||||
return compiler.compileModuleAsync(MockEmbeddedModule);
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
EmbedComponentsService,
|
||||
{ provide: NgModuleFactoryLoader, useClass: MockNgModuleFactoryLoader },
|
||||
{
|
||||
provide: EMBEDDED_COMPONENTS,
|
||||
useValue: {
|
||||
[testEagerEmbeddedSelectors.join(',')]: testEagerEmbeddedComponents,
|
||||
[testLazyEmbeddedSelectors.join(',')]: mockEmbeddedModulePath,
|
||||
},
|
||||
},
|
||||
],
|
||||
declarations: [testEagerEmbeddedComponents],
|
||||
entryComponents: [testEagerEmbeddedComponents],
|
||||
})
|
||||
export class TestModule { }
|
@ -200,8 +200,10 @@ function runProtractorAoT(appDir, outputFile) {
|
||||
// All protractor output is appended to the outputFile.
|
||||
// CLI version
|
||||
function runE2eTestsCLI(appDir, outputFile) {
|
||||
// --preserve-symlinks is needed due the symlinked node_modules in each example
|
||||
const e2eSpawn = spawnExt('yarn', ['e2e', '--preserve-symlinks'], { cwd: appDir });
|
||||
// `--preserve-symlinks` is needed due the symlinked `node_modules/` in each example.
|
||||
// `--no-webdriver-update` is needed to preserve the ChromeDriver version already installed.
|
||||
const args = ['e2e', '--preserve-symlinks', '--no-webdriver-update'];
|
||||
const e2eSpawn = spawnExt('yarn', args, { cwd: appDir });
|
||||
return e2eSpawn.promise.then(
|
||||
function () {
|
||||
fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`);
|
||||
|
@ -9,7 +9,6 @@
|
||||
"exclude": [
|
||||
"test.ts",
|
||||
"**/*.spec.ts",
|
||||
"testing/**",
|
||||
"**/*.1.*"
|
||||
"**/testing/*"
|
||||
]
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"http-server": "http-server",
|
||||
"protractor": "protractor",
|
||||
"webdriver:update": "webdriver-manager update --standalone false --gecko false",
|
||||
"webdriver:update": "webdriver-manager update --standalone false --gecko false $CHROMEDRIVER_VERSION_ARG",
|
||||
"postinstall": "yarn webdriver:update"
|
||||
},
|
||||
"keywords": [],
|
||||
|
223
aio/yarn.lock
223
aio/yarn.lock
@ -17,6 +17,12 @@
|
||||
dependencies:
|
||||
source-map "^0.5.6"
|
||||
|
||||
"@angular-devkit/core@0.0.21":
|
||||
version "0.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-0.0.21.tgz#e2ba4ac0a4e1156f884c083b15eb1c26ddfb2ba8"
|
||||
dependencies:
|
||||
source-map "^0.5.6"
|
||||
|
||||
"@angular-devkit/schematics@~0.0.34":
|
||||
version "0.0.34"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-0.0.34.tgz#c3ef61b0e49e585d9982f2828e9a67b3879a6b1b"
|
||||
@ -26,27 +32,27 @@
|
||||
minimist "^1.2.0"
|
||||
rxjs "^5.4.2"
|
||||
|
||||
"@angular/animations@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-5.0.0.tgz#b5ad199c67f93f759544477effe6679e154991fb"
|
||||
"@angular/animations@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-5.1.0-beta.2.tgz#2ed05bfa0ed22d6d1550658785e965c1fbfec5a7"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/cdk@^2.0.0-beta.12":
|
||||
version "2.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-2.0.0-beta.12.tgz#3a243cb62b93f4e039120ba70f900dc9e235622e"
|
||||
"@angular/cdk@^5.0.0-rc.1":
|
||||
version "5.0.0-rc.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-5.0.0-rc.1.tgz#7d6d937fea50074962db8ce02664b164401d197d"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/cli@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-1.5.0.tgz#2abc3ff1648d54ad4a14f82f9d517f371370406c"
|
||||
"@angular/cli@^1.6.0-rc.0":
|
||||
version "1.6.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-1.6.0-rc.0.tgz#e6bf974dcb2263e026d3d4ffa4480e4e78f9c7cf"
|
||||
dependencies:
|
||||
"@angular-devkit/build-optimizer" "~0.0.31"
|
||||
"@angular-devkit/schematics" "~0.0.34"
|
||||
"@ngtools/json-schema" "1.1.0"
|
||||
"@ngtools/webpack" "1.8.0"
|
||||
"@schematics/angular" "~0.1.0"
|
||||
"@ngtools/webpack" "1.9.0-rc.0"
|
||||
"@schematics/angular" "~0.1.5"
|
||||
autoprefixer "^6.5.3"
|
||||
chalk "~2.2.0"
|
||||
circular-dependency-plugin "^3.0.0"
|
||||
@ -70,13 +76,14 @@
|
||||
license-webpack-plugin "^1.0.0"
|
||||
lodash "^4.11.1"
|
||||
memory-fs "^0.4.1"
|
||||
minimatch "^3.0.4"
|
||||
node-modules-path "^1.0.0"
|
||||
nopt "^4.0.1"
|
||||
opn "~5.1.0"
|
||||
portfinder "~1.0.12"
|
||||
postcss-custom-properties "^6.1.0"
|
||||
postcss-loader "^1.3.3"
|
||||
postcss-url "^5.1.2"
|
||||
postcss-loader "^2.0.8"
|
||||
postcss-url "^7.1.2"
|
||||
raw-loader "^0.5.1"
|
||||
resolve "^1.1.7"
|
||||
rxjs "^5.5.2"
|
||||
@ -101,74 +108,74 @@
|
||||
optionalDependencies:
|
||||
node-sass "^4.3.0"
|
||||
|
||||
"@angular/common@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-5.0.0.tgz#f96d66a517b995d1ba9b28309f15c2e359675825"
|
||||
"@angular/common@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/common/-/common-5.1.0-beta.2.tgz#027b16b8d2f63eb14d9fbc84a0a5dd91945885d6"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/compiler-cli@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-5.0.0.tgz#0ecbb937d84a4f8dd94f0c2a47b07d2e4694c853"
|
||||
"@angular/compiler-cli@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-5.1.0-beta.2.tgz#62b63e30bdae910c322a62b76fa790dd4a6cdf53"
|
||||
dependencies:
|
||||
chokidar "^1.4.2"
|
||||
minimist "^1.2.0"
|
||||
reflect-metadata "^0.1.2"
|
||||
tsickle "^0.24.0"
|
||||
tsickle "^0.25.5"
|
||||
|
||||
"@angular/compiler@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-5.0.0.tgz#b9ffbf18c8a39d8b7dacec473193a90e24cc2bc9"
|
||||
"@angular/compiler@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-5.1.0-beta.2.tgz#6c88c3485558dcf85144f55edb1299d99cdb3fec"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/core@^5.0.0-rc.9":
|
||||
version "5.0.0-rc.9"
|
||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-5.0.0-rc.9.tgz#0aab5d2d9b31ea530a41bb1e3009504d1bd64673"
|
||||
"@angular/core@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/core/-/core-5.1.0-beta.2.tgz#e94b21cae4479caed9486239b065302a97c5fd4f"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/forms@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-5.0.0.tgz#c7fddfa35396759ae9852920a30cdda8c41ed1de"
|
||||
"@angular/forms@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-5.1.0-beta.2.tgz#feeee29041cce227cc50e254ebecc2f19dc529ee"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/http@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/http/-/http-5.0.0.tgz#0728a2be0cfbb078727c5eb87d4c85d53fec9a51"
|
||||
"@angular/http@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/http/-/http-5.1.0-beta.2.tgz#935beaba2afea192d6a75a1c3b8d7dfd787641b0"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/material@^2.0.0-beta.12":
|
||||
version "2.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.12.tgz#71b6d0b7b021891e5d0e3688c1d4bd78c7457f58"
|
||||
"@angular/material@^5.0.0-rc.1":
|
||||
version "5.0.0-rc.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular/material/-/material-5.0.0-rc.1.tgz#63456b7568c102b6bb7983a2837cc317350fe270"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/platform-browser-dynamic@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.0.0.tgz#887e106c8b103b0415cf6156a425da6d83f4c89d"
|
||||
"@angular/platform-browser-dynamic@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.1.0-beta.2.tgz#bee1d37f7300030edd855edf66311b0d493252d5"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/platform-browser@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-5.0.0.tgz#c7038f7cde80705b62014897231e182eec976fed"
|
||||
"@angular/platform-browser@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-5.1.0-beta.2.tgz#ccfca9d172f033137c83f2fbe8b702fe7204c5d5"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@angular/platform-server@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-5.0.0.tgz#877d25ef814af92fffc7b0b523b971a6ff222018"
|
||||
"@angular/platform-server@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-5.1.0-beta.2.tgz#a36583b274f263eeb9e1c23f6f0b83c36cc4a72a"
|
||||
dependencies:
|
||||
domino "^1.0.29"
|
||||
tslib "^1.7.1"
|
||||
xhr2 "^0.1.4"
|
||||
|
||||
"@angular/router@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@angular/router/-/router-5.0.0.tgz#fe4b521a6738408bce30f93a53499140c93a4f76"
|
||||
"@angular/router@^5.1.0-beta.2":
|
||||
version "5.1.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular/router/-/router-5.1.0-beta.2.tgz#a22b8c0e08b81c8b0950b9a668aa893e9f1c0e4c"
|
||||
dependencies:
|
||||
tslib "^1.7.1"
|
||||
|
||||
@ -254,9 +261,9 @@
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/json-schema/-/json-schema-1.1.0.tgz#c3a0c544d62392acc2813a42c8a0dc6f58f86922"
|
||||
|
||||
"@ngtools/webpack@1.8.0":
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.8.0.tgz#443204e016aa3a287544eacadb4c95964ae6e2c4"
|
||||
"@ngtools/webpack@1.9.0-rc.0":
|
||||
version "1.9.0-rc.0"
|
||||
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.9.0-rc.0.tgz#632e91c0e888e20c717eabeef58107e24d4ed663"
|
||||
dependencies:
|
||||
chalk "~2.2.0"
|
||||
enhanced-resolve "^3.1.0"
|
||||
@ -266,11 +273,11 @@
|
||||
source-map "^0.5.6"
|
||||
tree-kill "^1.0.0"
|
||||
|
||||
"@schematics/angular@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-0.1.0.tgz#cd6c445ead33144a532523d1ccac68c38a2b0050"
|
||||
"@schematics/angular@~0.1.5":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-0.1.7.tgz#2306aeec118ca185e180882eff54f5116de4ef05"
|
||||
dependencies:
|
||||
"@angular-devkit/core" "0.0.20"
|
||||
"@angular-devkit/core" "0.0.21"
|
||||
|
||||
"@types/core-js@^0.9.41":
|
||||
version "0.9.43"
|
||||
@ -704,7 +711,7 @@ async-foreach@^0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
|
||||
|
||||
async@0.2.x, async@~0.2.6:
|
||||
async@0.2.x:
|
||||
version "0.2.10"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
||||
|
||||
@ -1291,7 +1298,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
|
||||
strip-ansi "^3.0.0"
|
||||
supports-color "^2.0.0"
|
||||
|
||||
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0:
|
||||
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
|
||||
dependencies:
|
||||
@ -2093,6 +2100,10 @@ csv-streamify@^3.0.4:
|
||||
dependencies:
|
||||
through2 "2.0.1"
|
||||
|
||||
cuint@latest:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
|
||||
|
||||
currently-unhandled@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
|
||||
@ -2347,14 +2358,6 @@ diffie-hellman@^5.0.0:
|
||||
miller-rabin "^4.0.0"
|
||||
randombytes "^2.0.0"
|
||||
|
||||
directory-encoder@^0.7.2:
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/directory-encoder/-/directory-encoder-0.7.2.tgz#59b4e2aa4f25422f6c63b527b462f5e2d0dd2c58"
|
||||
dependencies:
|
||||
fs-extra "^0.23.1"
|
||||
handlebars "^1.3.0"
|
||||
img-stats "^0.5.2"
|
||||
|
||||
dns-equal@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
|
||||
@ -3674,14 +3677,6 @@ handle-thing@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
|
||||
|
||||
handlebars@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-1.3.0.tgz#9e9b130a93e389491322d975cf3ec1818c37ce34"
|
||||
dependencies:
|
||||
optimist "~0.3"
|
||||
optionalDependencies:
|
||||
uglify-js "~2.3"
|
||||
|
||||
handlebars@^4.0.3:
|
||||
version "4.0.11"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc"
|
||||
@ -4123,12 +4118,6 @@ image-ssim@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/image-ssim/-/image-ssim-0.2.0.tgz#83b42c7a2e6e4b85505477fe6917f5dbc56420e5"
|
||||
|
||||
img-stats@^0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/img-stats/-/img-stats-0.5.2.tgz#c203496c42f2d9eb2e5ab8232fa756bab32c9e2b"
|
||||
dependencies:
|
||||
xmldom "^0.1.19"
|
||||
|
||||
immediate@~3.0.5:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
@ -4627,7 +4616,7 @@ isurl@^1.0.0-alpha5:
|
||||
has-to-string-tag-x "^1.2.0"
|
||||
is-object "^1.0.1"
|
||||
|
||||
jasmine-core@^2.6.4, jasmine-core@~2.8.0:
|
||||
jasmine-core@^2.8.0, jasmine-core@~2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e"
|
||||
|
||||
@ -4674,7 +4663,7 @@ jpeg-js@0.1.2, jpeg-js@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.1.2.tgz#135b992c0575c985cfa0f494a3227ed238583ece"
|
||||
|
||||
js-base64@^2.1.5, js-base64@^2.1.8, js-base64@^2.1.9:
|
||||
js-base64@^2.1.8, js-base64@^2.1.9:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf"
|
||||
|
||||
@ -5863,7 +5852,7 @@ object-assign@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@^4.0.1, object-assign@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
@ -5938,12 +5927,6 @@ optimist@0.6.x, optimist@^0.6.1, optimist@~0.6.0, optimist@~0.6.1:
|
||||
minimist "~0.0.1"
|
||||
wordwrap "~0.0.2"
|
||||
|
||||
optimist@~0.3, optimist@~0.3.5:
|
||||
version "0.3.7"
|
||||
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9"
|
||||
dependencies:
|
||||
wordwrap "~0.0.2"
|
||||
|
||||
optionator@^0.8.1, optionator@^0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
|
||||
@ -6383,14 +6366,14 @@ postcss-load-plugins@^2.3.0:
|
||||
cosmiconfig "^2.1.1"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
postcss-loader@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-1.3.3.tgz#a621ea1fa29062a83972a46f54486771301916eb"
|
||||
postcss-loader@^2.0.8:
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.8.tgz#8c67ddb029407dfafe684a406cfc16bad2ce0814"
|
||||
dependencies:
|
||||
loader-utils "^1.0.2"
|
||||
object-assign "^4.1.1"
|
||||
postcss "^5.2.15"
|
||||
loader-utils "^1.1.0"
|
||||
postcss "^6.0.0"
|
||||
postcss-load-config "^1.2.0"
|
||||
schema-utils "^0.3.0"
|
||||
|
||||
postcss-merge-idents@^2.1.5:
|
||||
version "2.1.7"
|
||||
@ -6548,17 +6531,15 @@ postcss-unique-selectors@^2.0.2:
|
||||
postcss "^5.0.4"
|
||||
uniqs "^2.0.0"
|
||||
|
||||
postcss-url@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss-url/-/postcss-url-5.1.2.tgz#98b3165be8d592471cb0caadde2c0d1f832f133e"
|
||||
postcss-url@^7.1.2:
|
||||
version "7.2.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-url/-/postcss-url-7.2.1.tgz#bf47ff1b5395538567cea19ef3241a70fb925f5c"
|
||||
dependencies:
|
||||
directory-encoder "^0.7.2"
|
||||
js-base64 "^2.1.5"
|
||||
mime "^1.2.11"
|
||||
minimatch "^3.0.0"
|
||||
mime "^1.4.1"
|
||||
minimatch "^3.0.4"
|
||||
mkdirp "^0.5.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
postcss "^5.0.0"
|
||||
postcss "^6.0.1"
|
||||
xxhashjs "^0.2.1"
|
||||
|
||||
postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
|
||||
version "3.3.0"
|
||||
@ -6572,7 +6553,7 @@ postcss-zindex@^2.0.1:
|
||||
postcss "^5.0.4"
|
||||
uniqs "^2.0.0"
|
||||
|
||||
postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.15, postcss@^5.2.16:
|
||||
postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16:
|
||||
version "5.2.18"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
|
||||
dependencies:
|
||||
@ -6581,6 +6562,14 @@ postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.
|
||||
source-map "^0.5.6"
|
||||
supports-color "^3.2.3"
|
||||
|
||||
postcss@^6.0.0:
|
||||
version "6.0.14"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885"
|
||||
dependencies:
|
||||
chalk "^2.3.0"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^4.4.0"
|
||||
|
||||
postcss@^6.0.1, postcss@^6.0.13:
|
||||
version "6.0.13"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f"
|
||||
@ -7319,7 +7308,7 @@ rx@2.3.24:
|
||||
version "2.3.24"
|
||||
resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7"
|
||||
|
||||
rxjs@^5.4.2, rxjs@^5.5.0:
|
||||
rxjs@^5.4.2:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.0.tgz#26d8f3866eb700e247e0728a147c3d628993d812"
|
||||
dependencies:
|
||||
@ -7729,7 +7718,7 @@ source-map-support@^0.4.0, source-map-support@^0.4.1, source-map-support@^0.4.15
|
||||
dependencies:
|
||||
source-map "^0.5.6"
|
||||
|
||||
source-map@0.1.x, source-map@~0.1.7:
|
||||
source-map@0.1.x:
|
||||
version "0.1.43"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
|
||||
dependencies:
|
||||
@ -8379,9 +8368,9 @@ tsconfig@^6.0.0:
|
||||
strip-bom "^3.0.0"
|
||||
strip-json-comments "^2.0.0"
|
||||
|
||||
tsickle@^0.24.0:
|
||||
version "0.24.1"
|
||||
resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.24.1.tgz#039343b205bf517a333b0703978892f80a7d848e"
|
||||
tsickle@^0.25.5:
|
||||
version "0.25.5"
|
||||
resolved "https://registry.yarnpkg.com/tsickle/-/tsickle-0.25.5.tgz#2891d29f97c4aab1306e06378d8496d1765a4bfe"
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
mkdirp "^0.5.1"
|
||||
@ -8478,14 +8467,6 @@ uglify-js@^2.6, uglify-js@^2.8.29:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@~2.3:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.3.6.tgz#fa0984770b428b7a9b2a8058f46355d14fef211a"
|
||||
dependencies:
|
||||
async "~0.2.6"
|
||||
optimist "~0.3.5"
|
||||
source-map "~0.1.7"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@ -9299,10 +9280,6 @@ xmlbuilder@>=1.0.0, xmlbuilder@~9.0.1:
|
||||
version "9.0.4"
|
||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f"
|
||||
|
||||
xmldom@^0.1.19:
|
||||
version "0.1.27"
|
||||
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
|
||||
|
||||
xmlhttprequest-ssl@1.5.3:
|
||||
version "1.5.3"
|
||||
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d"
|
||||
@ -9311,6 +9288,12 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||
|
||||
xxhashjs@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.1.tgz#9bbe9be896142976dfa34c061b2d068c43d30de0"
|
||||
dependencies:
|
||||
cuint latest
|
||||
|
||||
y18n@^3.2.0, y18n@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
|
||||
|
@ -21,16 +21,16 @@ following products on your development machine:
|
||||
[Windows](http://windows.github.com)); [GitHub's Guide to Installing
|
||||
Git](https://help.github.com/articles/set-up-git) is a good source of information.
|
||||
|
||||
* [Node.js](http://nodejs.org), (version `>=6.9.5 <7.0.0`) which is used to run a development web server,
|
||||
run tests, and generate distributable files. We also use Node's Package Manager, `npm`
|
||||
(version `>=3.10.7 <4.0.0`), which comes with Node. Depending on your system, you can install Node either from
|
||||
source or as a pre-packaged bundle.
|
||||
* [Node.js](http://nodejs.org), (version specified in the engines field of [`package.json`](../package.json)) which is used to run a development web server,
|
||||
run tests, and generate distributable files.
|
||||
|
||||
* [Yarn](https://yarnpkg.com) (version `>=1.0.2 <2.0.0`) which is used to install dependencies.
|
||||
* [Yarn](https://yarnpkg.com) (version specified in the engines field of [`package.json`](../package.json)) which is used to install dependencies.
|
||||
|
||||
* [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]
|
||||
|
||||
## Getting the Sources
|
||||
|
||||
Fork and clone the Angular repository:
|
||||
@ -61,19 +61,11 @@ Next, install the JavaScript modules needed to build and test Angular:
|
||||
yarn install
|
||||
```
|
||||
|
||||
**Optional**: In this document, we make use of project local `npm` package scripts and binaries
|
||||
(stored under `./node_modules/.bin`) by prefixing these command invocations with `$(npm bin)`; in
|
||||
particular `gulp` and `protractor` commands. If you prefer, you can drop this path prefix by either:
|
||||
**Optional**: In this document, we make use of installed npm package scripts and binaries
|
||||
(stored under `./node_modules/.bin`) by prefixing these command invocations with `$(yarn bin)`; in
|
||||
particular `gulp` and `protractor` commands.
|
||||
|
||||
|
||||
## Installing Bower Modules
|
||||
|
||||
Now run `bower` to install additional dependencies:
|
||||
|
||||
```shell
|
||||
# Install other Angular project dependencies (bower.json)
|
||||
bower install
|
||||
```
|
||||
|
||||
## Windows only
|
||||
|
||||
|
@ -2,9 +2,25 @@ package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "node_modules",
|
||||
srcs = glob([
|
||||
"node_modules/**/*.js",
|
||||
"node_modules/**/*.d.ts",
|
||||
"node_modules/**/*.json",
|
||||
])
|
||||
# Workaround https://github.com/bazelbuild/bazel/issues/4242
|
||||
# Can't just glob(["node_modules/**/*.{js,d.ts,json}"])
|
||||
srcs = glob(["/".join([
|
||||
"node_modules",
|
||||
pkg,
|
||||
"**",
|
||||
ext,
|
||||
]) for pkg in [
|
||||
"@angular",
|
||||
"@types",
|
||||
"bytebuffer",
|
||||
"protobufjs",
|
||||
"reflect-metadata",
|
||||
"tsickle",
|
||||
"typescript",
|
||||
"zone.js",
|
||||
] for ext in [
|
||||
"*.js",
|
||||
"*.json",
|
||||
"*.d.ts",
|
||||
]]),
|
||||
)
|
||||
|
@ -1,24 +1,36 @@
|
||||
workspace(name = "bazel_integration_test")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
|
||||
git_repository(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
remote = "https://github.com/bazelbuild/rules_nodejs.git",
|
||||
tag = "0.2.1",
|
||||
tag = "0.3.1",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
|
||||
node_repositories(package_json = ["//:package.json"])
|
||||
|
||||
local_repository(
|
||||
git_repository(
|
||||
name = "build_bazel_rules_typescript",
|
||||
path = "node_modules/@bazel/typescript",
|
||||
remote = "https://github.com/bazelbuild/rules_typescript.git",
|
||||
tag = "0.6.0",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_repositories")
|
||||
|
||||
ts_repositories()
|
||||
|
||||
local_repository(
|
||||
name = "angular",
|
||||
path = "node_modules/@angular/bazel",
|
||||
)
|
||||
|
||||
local_repository(
|
||||
name = "rxjs",
|
||||
path = "node_modules/rxjs/src",
|
||||
)
|
||||
|
||||
git_repository(
|
||||
name = "io_bazel_rules_sass",
|
||||
remote = "https://github.com/bazelbuild/rules_sass.git",
|
||||
|
@ -20,6 +20,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "ngc -p angular.tsconfig.json",
|
||||
"test": "bazel build ... --noshow_progress"
|
||||
"test": "WORKAROUND https://github.com/bazelbuild/bazel/issues/4242, can't build ...",
|
||||
"test": "bazel build //src/... --noshow_progress"
|
||||
}
|
||||
}
|
@ -6,6 +6,6 @@ exports_files(["tsconfig.json"])
|
||||
ng_module(
|
||||
name = "src",
|
||||
srcs = glob(["*.ts"]),
|
||||
deps = ["//src/hello-world"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = ["//src/hello-world"],
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
load("@io_bazel_rules_sass//sass:sass.bzl", "sass_binary")
|
||||
|
||||
@ -10,6 +11,9 @@ sass_binary(
|
||||
ng_module(
|
||||
name = "hello-world",
|
||||
srcs = glob(["*.ts"]),
|
||||
tsconfig = "//src:tsconfig.json",
|
||||
assets = [":hello-world-styles.css"],
|
||||
tsconfig = "//src:tsconfig.json",
|
||||
# FIXME(alexeagle): the rxjs dep should come from Angular, but if we use the
|
||||
# npm distro of angular there is no ts_library rule to propagate the dep.
|
||||
deps = ["@rxjs"],
|
||||
)
|
||||
|
@ -10,7 +10,7 @@
|
||||
"ngc": "ngc -p tsconfig.json",
|
||||
"rollup": "rollup -f iife -c rollup.config.js -o dist/bundle.es2015.js",
|
||||
"rollup:lazy": "rollup -f cjs -c rollup.lazy.config.js -o dist/lazy.bundle.es2015.js",
|
||||
"postinstall": "webdriver-manager update --gecko false",
|
||||
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG",
|
||||
"preprotractor": "tsc -p e2e",
|
||||
"protractor": "protractor e2e/protractor.config.js",
|
||||
"serve": "lite-server -c e2e/browser.config.json",
|
||||
|
@ -22,7 +22,7 @@
|
||||
"protractor": "file:../../node_modules/protractor"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "webdriver-manager update --gecko false",
|
||||
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG",
|
||||
"closure": "java -jar node_modules/google-closure-compiler/compiler.jar --flagfile closure.conf",
|
||||
"test": "ngc && yarn run closure && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first",
|
||||
"serve": "lite-server -c e2e/browser.config.json",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"postinstall": "webdriver-manager update --gecko false",
|
||||
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG",
|
||||
"test": "concurrently \"npm run serve\" \"npm run protractor\" --kill-others --success first",
|
||||
"serve": "lite-server -c bs-config.e2e.json",
|
||||
"preprotractor": "tsc -p e2e",
|
||||
|
@ -22,7 +22,7 @@
|
||||
"protractor": "file:../../node_modules/protractor"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "webdriver-manager update --gecko false",
|
||||
"postinstall": "webdriver-manager update --gecko false --standalone false $CHROMEDRIVER_VERSION_ARG",
|
||||
"closure": "java -jar node_modules/google-closure-compiler/compiler.jar --flagfile closure.conf",
|
||||
"test": "ngc && yarn run closure && concurrently \"yarn run serve\" \"yarn run protractor\" --kill-others --success first",
|
||||
"serve": "lite-server -c e2e/browser.config.json",
|
||||
|
13
package.json
13
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "5.1.0",
|
||||
"version": "5.1.1",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
@ -16,14 +16,16 @@
|
||||
"url": "https://github.com/angular/angular.git"
|
||||
},
|
||||
"scripts": {
|
||||
"buildifier": "bazel build @com_github_bazelbuild_buildtools//buildifier && find . -type f \\( -name BUILD -or -name BUILD.bazel \\) ! -path \"*/node_modules/*\" | xargs $(bazel info bazel-bin)/external/com_github_bazelbuild_buildtools/buildifier/buildifier",
|
||||
"preinstall": "node -e \"if(process.env.npm_execpath.indexOf('yarn') === -1) throw new Error('Please use Yarn instead of NPM to install dependencies. See: https://yarnpkg.com/lang/en/docs/install/')\"",
|
||||
"postinstall": "webdriver-manager update --gecko false",
|
||||
"postinstall": "yarn update-webdriver",
|
||||
"update-webdriver": "webdriver-manager update --gecko false $CHROMEDRIVER_VERSION_ARG",
|
||||
"check-env": "gulp check-env"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.3",
|
||||
"rxjs": "^5.5.2",
|
||||
"rxjs": "5.5.5",
|
||||
"tslib": "^1.7.1",
|
||||
"zone.js": "^0.8.12"
|
||||
},
|
||||
@ -31,7 +33,7 @@
|
||||
"fsevents": "1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bazel/typescript": "0.3.2",
|
||||
"@bazel/ibazel": "^0.1.1",
|
||||
"@types/angularjs": "1.5.14-alpha",
|
||||
"@types/base64-js": "1.2.5",
|
||||
"@types/chokidar": "1.7.3",
|
||||
@ -51,7 +53,7 @@
|
||||
"canonical-path": "0.0.2",
|
||||
"chokidar": "1.7.0",
|
||||
"clang-format": "1.0.41",
|
||||
"cldr": "4.5.0",
|
||||
"cldr": "4.7.0",
|
||||
"cldr-data-downloader": "0.3.2",
|
||||
"cldrjs": "0.5.0",
|
||||
"conventional-changelog": "1.1.0",
|
||||
@ -97,6 +99,7 @@
|
||||
"tsickle": "0.25.5",
|
||||
"tslint": "5.7.0",
|
||||
"tslint-eslint-rules": "4.1.1",
|
||||
"tsutils": "2.12.1",
|
||||
"typescript": "2.5.x",
|
||||
"uglify-js": "2.8.29",
|
||||
"universal-analytics": "0.4.15",
|
||||
|
@ -1 +1,20 @@
|
||||
exports_files(["tsconfig-build.json"])
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"tsconfig-build.json",
|
||||
"tsconfig.json",
|
||||
])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_config", "ts_library")
|
||||
|
||||
ts_config(
|
||||
name = "tsconfig",
|
||||
src = ":tsconfig-build.json",
|
||||
deps = [],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "types",
|
||||
srcs = glob(["*.ts"]),
|
||||
tsconfig = ":tsconfig",
|
||||
)
|
||||
|
18
packages/animations/BUILD.bazel
Normal file
18
packages/animations/BUILD.bazel
Normal file
@ -0,0 +1,18 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "animations",
|
||||
srcs = glob(
|
||||
[
|
||||
"*.ts",
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/animations",
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages/core",
|
||||
],
|
||||
)
|
18
packages/animations/browser/BUILD.bazel
Normal file
18
packages/animations/browser/BUILD.bazel
Normal file
@ -0,0 +1,18 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "browser",
|
||||
srcs = glob(
|
||||
[
|
||||
"*.ts",
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/animations/browser",
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages/animations",
|
||||
],
|
||||
)
|
@ -65,13 +65,12 @@ function parseAnimationAlias(alias: string, errors: string[]): string|Transition
|
||||
}
|
||||
}
|
||||
|
||||
const TRUE_BOOLEAN_VALUES = new Set<string>();
|
||||
TRUE_BOOLEAN_VALUES.add('true');
|
||||
TRUE_BOOLEAN_VALUES.add('1');
|
||||
|
||||
const FALSE_BOOLEAN_VALUES = new Set<string>();
|
||||
FALSE_BOOLEAN_VALUES.add('false');
|
||||
FALSE_BOOLEAN_VALUES.add('0');
|
||||
// DO NOT REFACTOR ... keep the follow set instantiations
|
||||
// with the values intact (closure compiler for some reason
|
||||
// removes follow-up lines that add the values outside of
|
||||
// the constructor...
|
||||
const TRUE_BOOLEAN_VALUES = new Set<string>(['true', '1']);
|
||||
const FALSE_BOOLEAN_VALUES = new Set<string>(['false', '0']);
|
||||
|
||||
function makeLambdaFromStates(lhs: string, rhs: string): TransitionMatcherFn {
|
||||
const LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs);
|
||||
|
@ -166,12 +166,30 @@ if (typeof Element != 'undefined') {
|
||||
};
|
||||
}
|
||||
|
||||
function containsVendorPrefix(prop: string): boolean {
|
||||
// Webkit is the only real popular vendor prefix nowadays
|
||||
// cc: http://shouldiprefix.com/
|
||||
return prop.substring(1, 6) == 'ebkit'; // webkit or Webkit
|
||||
}
|
||||
|
||||
let _CACHED_BODY: {style: any}|null = null;
|
||||
let _IS_WEBKIT = false;
|
||||
export function validateStyleProperty(prop: string): boolean {
|
||||
if (!_CACHED_BODY) {
|
||||
_CACHED_BODY = getBodyNode() || {};
|
||||
_IS_WEBKIT = _CACHED_BODY !.style ? ('WebkitAppearance' in _CACHED_BODY !.style) : false;
|
||||
}
|
||||
return _CACHED_BODY !.style ? prop in _CACHED_BODY !.style : true;
|
||||
|
||||
let result = true;
|
||||
if (_CACHED_BODY !.style && !containsVendorPrefix(prop)) {
|
||||
result = prop in _CACHED_BODY !.style;
|
||||
if (!result && _IS_WEBKIT) {
|
||||
const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.substr(1);
|
||||
result = camelProp in _CACHED_BODY !.style;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getBodyNode(): any|null {
|
||||
|
@ -312,9 +312,13 @@ export class AnimationTransitionNamespace {
|
||||
// If there are no animations found for any of the nodes then clear the cache
|
||||
// for the element.
|
||||
this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true).forEach(elm => {
|
||||
// this means that an inner remove() operation has already kicked off
|
||||
// the animation on this element...
|
||||
if (elm[REMOVAL_FLAG]) return;
|
||||
|
||||
const namespaces = this._engine.fetchNamespacesByElement(elm);
|
||||
if (namespaces.size) {
|
||||
namespaces.forEach(ns => { ns.triggerLeaveAnimation(elm, context, false, true); });
|
||||
namespaces.forEach(ns => ns.triggerLeaveAnimation(elm, context, false, true));
|
||||
} else {
|
||||
this.clearElementCache(elm);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ export class WebAnimationsPlayer implements AnimationPlayer {
|
||||
|
||||
const keyframes = this.keyframes.map(styles => copyStyles(styles, false));
|
||||
const previousStyleProps = Object.keys(this.previousStyles);
|
||||
if (previousStyleProps.length) {
|
||||
if (previousStyleProps.length && keyframes.length) {
|
||||
let startingKeyframe = keyframes[0];
|
||||
let missingStyleProps: string[] = [];
|
||||
previousStyleProps.forEach(prop => {
|
||||
|
17
packages/animations/browser/test/BUILD.bazel
Normal file
17
packages/animations/browser/test/BUILD.bazel
Normal file
@ -0,0 +1,17 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "test",
|
||||
testonly = 1,
|
||||
srcs = glob(["**/*.ts"]),
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/animations",
|
||||
"//packages/animations/browser",
|
||||
"//packages/animations/browser/testing",
|
||||
"//packages/core",
|
||||
],
|
||||
)
|
@ -216,6 +216,26 @@ export function main() {
|
||||
.toThrowError(
|
||||
/The provided animation property "abc" is not a supported CSS property for animations/);
|
||||
});
|
||||
|
||||
it('should allow a vendor-prefixed property to be used in an animation sequence without throwing an error',
|
||||
() => {
|
||||
const steps = [
|
||||
style({webkitTransform: 'translateX(0px)'}),
|
||||
animate(1000, style({webkitTransform: 'translateX(100px)'}))
|
||||
];
|
||||
|
||||
expect(() => validateAndThrowAnimationSequence(steps)).not.toThrow();
|
||||
});
|
||||
|
||||
it('should allow for old CSS properties (like transform) to be auto-prefixed by webkit',
|
||||
() => {
|
||||
const steps = [
|
||||
style({transform: 'translateX(-100px)'}),
|
||||
animate(1000, style({transform: 'translateX(500px)'}))
|
||||
];
|
||||
|
||||
expect(() => validateAndThrowAnimationSequence(steps)).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('keyframe building', () => {
|
||||
|
@ -33,6 +33,24 @@ export function main() {
|
||||
expect(p.log).toEqual(['pause', 'play']);
|
||||
});
|
||||
|
||||
it('should allow an empty set of keyframes with a set of previous styles', () => {
|
||||
const previousKeyframes = [
|
||||
{opacity: 0, offset: 0},
|
||||
{opacity: 1, offset: 1},
|
||||
];
|
||||
|
||||
const previousPlayer = new WebAnimationsPlayer(element, previousKeyframes, {duration: 1000});
|
||||
previousPlayer.play();
|
||||
previousPlayer.finish();
|
||||
previousPlayer.beforeDestroy();
|
||||
|
||||
const EMPTY_KEYFRAMES: any[] = [];
|
||||
const player =
|
||||
new WebAnimationsPlayer(element, EMPTY_KEYFRAMES, {duration: 1000}, [previousPlayer]);
|
||||
player.play();
|
||||
player.destroy();
|
||||
});
|
||||
|
||||
it('should not pause the player if created and started before initialized', () => {
|
||||
const keyframes = [
|
||||
{opacity: 0, offset: 0},
|
||||
@ -53,13 +71,13 @@ export function main() {
|
||||
player.onStart(() => log.push('started'));
|
||||
player.onDone(() => log.push('done'));
|
||||
|
||||
player.triggerCallback('start');
|
||||
(player as any).triggerCallback('start');
|
||||
expect(log).toEqual(['started']);
|
||||
|
||||
player.play();
|
||||
expect(log).toEqual(['started']);
|
||||
|
||||
player.triggerCallback('done');
|
||||
(player as any).triggerCallback('done');
|
||||
expect(log).toEqual(['started', 'done']);
|
||||
|
||||
player.finish();
|
||||
|
15
packages/animations/browser/testing/BUILD.bazel
Normal file
15
packages/animations/browser/testing/BUILD.bazel
Normal file
@ -0,0 +1,15 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "testing",
|
||||
testonly = 1,
|
||||
srcs = glob(["**/*.ts"]),
|
||||
module_name = "@angular/animations/browser/testing",
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages/animations",
|
||||
"//packages/animations/browser",
|
||||
],
|
||||
)
|
15
packages/animations/test/BUILD.bazel
Normal file
15
packages/animations/test/BUILD.bazel
Normal file
@ -0,0 +1,15 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "test",
|
||||
testonly = 1,
|
||||
srcs = glob(["test/**/*.ts"]),
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/animations",
|
||||
"//packages/core/testing",
|
||||
],
|
||||
)
|
@ -49,13 +49,13 @@ export function main() {
|
||||
player.onDone(() => log.push('done'));
|
||||
flushMicrotasks();
|
||||
|
||||
player.triggerCallback('start');
|
||||
(player as any).triggerCallback('start');
|
||||
expect(log).toEqual(['started']);
|
||||
|
||||
player.play();
|
||||
expect(log).toEqual(['started']);
|
||||
|
||||
player.triggerCallback('done');
|
||||
(player as any).triggerCallback('done');
|
||||
expect(log).toEqual(['started', 'done']);
|
||||
|
||||
player.finish();
|
||||
|
@ -9,7 +9,6 @@
|
||||
"typescript": ">=2.4.2 <2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bazel/typescript": "0.3.2",
|
||||
"@types/node": "6.0.84"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -4,41 +4,42 @@ load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
ts_library(
|
||||
name = "ngc_lib",
|
||||
srcs = [
|
||||
"index.ts",
|
||||
"extract_i18n.ts",
|
||||
"index.ts",
|
||||
],
|
||||
module_name = "@angular/bazel",
|
||||
tsconfig = ":tsconfig.json",
|
||||
visibility = ["//test/ngc-wrapped:__subpackages__"],
|
||||
deps = [
|
||||
# BEGIN-INTERNAL
|
||||
# Only needed when compiling within the Angular repo.
|
||||
# Users will get this dependency from node_modules.
|
||||
"@//packages/compiler-cli",
|
||||
# END-INTERNAL
|
||||
"@build_bazel_rules_typescript//internal/tsc_wrapped"
|
||||
"@build_bazel_rules_typescript//internal/tsc_wrapped",
|
||||
],
|
||||
tsconfig = ":tsconfig.json",
|
||||
visibility = ["//test/ngc-wrapped:__subpackages__"],
|
||||
)
|
||||
|
||||
nodejs_binary(
|
||||
name = "ngc-wrapped",
|
||||
data = [
|
||||
":ngc_lib",
|
||||
"@build_bazel_rules_typescript//internal:worker_protocol.proto",
|
||||
],
|
||||
# Entry point assumes the user is outside this WORKSPACE,
|
||||
# and references our rules with @angular//src/ngc-wrapped
|
||||
entry_point = "angular/src/ngc-wrapped/index.js",
|
||||
data = [
|
||||
":ngc_lib",
|
||||
"@build_bazel_rules_typescript//internal:worker_protocol.proto"
|
||||
],
|
||||
node_modules = "@build_bazel_rules_typescript_deps//:node_modules",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
nodejs_binary(
|
||||
name = "xi18n",
|
||||
# Entry point assumes the user is outside this WORKSPACE,
|
||||
# and references our rules with @angular//src/ngc-wrapped
|
||||
entry_point = "angular/src/ngc-wrapped/index.js/extract_i18n.js",
|
||||
data = [
|
||||
":ngc_lib",
|
||||
],
|
||||
# Entry point assumes the user is outside this WORKSPACE,
|
||||
# and references our rules with @angular//src/ngc-wrapped
|
||||
entry_point = "angular/src/ngc-wrapped/index.js/extract_i18n.js",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
@ -178,7 +178,7 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true,
|
||||
return relativeToRootDirs(importedFilePath, compilerOpts.rootDirs).replace(EXT, '');
|
||||
};
|
||||
ngHost.toSummaryFileName = (fileName: string, referringSrcFileName: string) =>
|
||||
ngHost.fileNameToModuleName(fileName, referringSrcFileName);
|
||||
relativeToRootDirs(fileName, compilerOpts.rootDirs).replace(EXT, '');
|
||||
if (allDepsCompiledWithBazel) {
|
||||
// Note: The default implementation would work as well,
|
||||
// but we can be faster as we know how `toSummaryFileName` works.
|
||||
|
@ -8,32 +8,32 @@ ts_library(
|
||||
"test_support.ts",
|
||||
"tsconfig_template.ts",
|
||||
],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = [
|
||||
# BEGIN-INTERNAL
|
||||
# Only needed when compiling within the Angular repo.
|
||||
# Users will get this dependency from node_modules.
|
||||
"@//packages/compiler-cli",
|
||||
# END-INTERNAL
|
||||
"//src/ngc-wrapped:ngc_lib"
|
||||
"//src/ngc-wrapped:ngc_lib",
|
||||
],
|
||||
tsconfig = ":tsconfig.json",
|
||||
)
|
||||
|
||||
# We need a filegroup so that we can refer
|
||||
# .d.ts files (by default, jasmine_node_test would get the .js files).
|
||||
filegroup(
|
||||
name = "angular_core",
|
||||
srcs = ["@//packages/core"]
|
||||
srcs = ["@//packages/core"],
|
||||
)
|
||||
|
||||
jasmine_node_test(
|
||||
name = "ngc_test",
|
||||
size = "small",
|
||||
srcs = [":ngc_test_lib"],
|
||||
data = [
|
||||
"@build_bazel_rules_typescript//internal:worker_protocol.proto",
|
||||
":angular_core",
|
||||
"//test/ngc-wrapped/empty:empty_tsconfig.json",
|
||||
"//test/ngc-wrapped/empty:tsconfig.json",
|
||||
"@build_bazel_rules_typescript//internal:worker_protocol.proto",
|
||||
],
|
||||
size="small",
|
||||
)
|
||||
|
@ -1,10 +1,10 @@
|
||||
load("@angular//:index.bzl", "ng_module")
|
||||
|
||||
package(default_visibility=["//test:__subpackages__"])
|
||||
package(default_visibility = ["//test:__subpackages__"])
|
||||
|
||||
ng_module(
|
||||
name = "empty",
|
||||
srcs = ["empty.ts"],
|
||||
deps = ["@//packages/core"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
deps = ["@//packages/core"],
|
||||
)
|
||||
|
@ -40,7 +40,7 @@ export function setup(
|
||||
bazelBin?: string,
|
||||
tsconfig?: string,
|
||||
} = {}): TestSupport {
|
||||
const runfilesPath = process.env['RUNFILES'];
|
||||
const runfilesPath = process.env['TEST_SRCDIR'];
|
||||
|
||||
const basePath = makeTempDir(runfilesPath);
|
||||
|
||||
@ -150,7 +150,7 @@ function makeTempDir(baseDir): string {
|
||||
}
|
||||
|
||||
export function listFilesRecursive(dir: string, fileList: string[] = []) {
|
||||
fs.readdirSync(dir).map(file => {
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
if (fs.statSync(path.join(dir, file)).isDirectory()) {
|
||||
listFilesRecursive(path.join(dir, file), fileList);
|
||||
} else {
|
||||
|
@ -68,6 +68,9 @@ export function createTsConfig(options: TsConfigOptions) {
|
||||
// Because we ask for :empty_tsconfig.json, we get the ES6 version which
|
||||
// expects to write externs, yet that doesn't work under this fixture.
|
||||
'tsickleExternsPath': '',
|
||||
// we don't copy the node_modules into our tmp dir, so we should look in
|
||||
// the original workspace directory for it
|
||||
'nodeModulesPrefix': '../angular_src/node_modules',
|
||||
},
|
||||
'files': options.files,
|
||||
'angularCompilerOptions': {
|
||||
|
@ -1,15 +1,19 @@
|
||||
package(default_visibility=["//visibility:public"])
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "common",
|
||||
srcs = glob(["**/*.ts"], exclude=[
|
||||
"http/**",
|
||||
"locales/**",
|
||||
"test/**",
|
||||
"testing/**",
|
||||
]),
|
||||
srcs = glob(
|
||||
[
|
||||
"*.ts",
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/common",
|
||||
deps = ["//packages/core"],
|
||||
tsconfig = ":tsconfig-build.json",
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages/core",
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
||||
|
20
packages/common/http/BUILD.bazel
Normal file
20
packages/common/http/BUILD.bazel
Normal file
@ -0,0 +1,20 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "http",
|
||||
srcs = glob(
|
||||
[
|
||||
"*.ts",
|
||||
"src/**/*.ts",
|
||||
],
|
||||
),
|
||||
module_name = "@angular/common/http",
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages/common",
|
||||
"//packages/core",
|
||||
"@rxjs",
|
||||
],
|
||||
)
|
14
packages/common/http/testing/BUILD.bazel
Normal file
14
packages/common/http/testing/BUILD.bazel
Normal file
@ -0,0 +1,14 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "testing",
|
||||
testonly = 1,
|
||||
srcs = glob(["testing/**/*.ts"]),
|
||||
module_name = "@angular/common/http/testing",
|
||||
tsconfig = "//packages:tsconfig",
|
||||
deps = [
|
||||
"//packages/common/http",
|
||||
],
|
||||
)
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 0, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['H:mm', 'H:mm:ss', 'H:mm:ss z', 'H:mm:ss zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,15 +18,15 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ', 'ت', 'ت', 'ك'],
|
||||
[
|
||||
'كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
|
||||
'تشرین الأول', 'تشرين الثاني', 'كانون الأول'
|
||||
'تشرين الأول', 'تشرين الثاني', 'كانون الأول'
|
||||
],
|
||||
[
|
||||
'كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
|
||||
@ -41,7 +41,7 @@ export default [
|
||||
],
|
||||
],
|
||||
[['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['HH:mm', 'HH:mm:ss', 'HH:mm:ss z', 'HH:mm:ss zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
@ -38,7 +38,7 @@ export default [
|
||||
,
|
||||
],
|
||||
['.', ',', ';', '%', '+', '-', 'E', '×', '‰', '∞', 'ليس رقمًا', ':'],
|
||||
['#,##0.###', '#,##0%', '¤ #,##0.00', '#E0'], 'ف.ج.ق.', 'فرنك جزر القمر',
|
||||
['#,##0.###', '#,##0%', '¤ #,##0.00', '#E0'], 'CF', 'فرنك جزر القمر',
|
||||
function(n: number):
|
||||
number {
|
||||
if (n === 0) return 0;
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['HH:mm', 'HH:mm:ss', 'HH:mm:ss z', 'HH:mm:ss zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 0, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 1, [6, 0],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 0, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 0, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,8 +18,8 @@ export default [
|
||||
[['ص', 'م'], , ['صباحًا', 'مساءً']],
|
||||
[
|
||||
['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
,
|
||||
['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'], ,
|
||||
['أحد', 'إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت']
|
||||
],
|
||||
,
|
||||
[
|
||||
@ -30,7 +30,7 @@ export default [
|
||||
],
|
||||
],
|
||||
, [['ق.م', 'م'], , ['قبل الميلاد', 'ميلادي']], 6, [5, 6],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM، y', 'EEEE، d MMMM، y'],
|
||||
['d/M/y', 'dd/MM/y', 'd MMMM y', 'EEEE، d MMMM y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -17,26 +17,30 @@ export default [
|
||||
],
|
||||
,
|
||||
[
|
||||
['S', 'M', 'T', 'W', 'T', 'F', 'S'], ['ৰবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
|
||||
['দেওবাৰ', 'সোমবাৰ', 'মঙ্গলবাৰ', 'বুধবাৰ', 'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ', 'শনিবাৰ'],
|
||||
['ৰবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি']
|
||||
['দ', 'স', 'ম', 'ব', 'ব', 'শ', 'শ'], ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহ', 'শুক্ৰ', 'শনি'],
|
||||
['দেওবাৰ', 'সোমবাৰ', 'মঙ্গলবাৰ', 'বুধবাৰ', 'বৃহস্পতিবাৰ', 'শুক্ৰবাৰ', 'শনিবাৰ'],
|
||||
['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহ', 'শুক্ৰ', 'শনি']
|
||||
],
|
||||
,
|
||||
[
|
||||
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
|
||||
['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
|
||||
['জ', 'ফ', 'ম', 'এ', 'ম', 'জ', 'জ', 'আ', 'ছ', 'অ', 'ন', 'ড'],
|
||||
['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে’', 'জুন', 'জুলাই', 'আগ', 'ছেপ্তে', 'অক্টো', 'নৱে', 'ডিচে'],
|
||||
[
|
||||
'জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ',
|
||||
'জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে’', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ',
|
||||
'নৱেম্বৰ', 'ডিচেম্বৰ'
|
||||
]
|
||||
],
|
||||
,
|
||||
[
|
||||
['BCE', 'CE'],
|
||||
,
|
||||
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
|
||||
['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে’', 'জুন', 'জুলাই', 'আগ', 'ছেপ্তে', 'অক্টো', 'নৱে', 'ডিচে'],
|
||||
[
|
||||
'জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে’', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ',
|
||||
'নৱেম্বৰ', 'ডিচেম্বৰ'
|
||||
]
|
||||
],
|
||||
0, [0, 0], ['y-MM-dd', 'y MMM d', 'y MMMM d', 'y MMMM d, EEEE'],
|
||||
['HH:mm', 'HH:mm:ss', 'HH:mm:ss z', 'HH:mm:ss zzzz'],
|
||||
[['খ্ৰী.পূ.', 'খ্ৰী.দ.'], , ['খ্ৰীষ্টপূৰ্ব', 'খ্ৰীষ্টাব্দ']], 0, [0, 0],
|
||||
['d-M-y', 'dd-MM-y', 'd MMMM, y', 'EEEE, d MMMM, y'],
|
||||
['h.mm. a', 'h.mm.ss a', 'h.mm.ss a z', 'h.mm.ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
,
|
||||
|
@ -31,13 +31,13 @@ export default [
|
||||
],
|
||||
, [['пр.Хр.', 'сл.Хр.'], , ['преди Христа', 'след Христа']], 1, [6, 0],
|
||||
['d.MM.yy \'г\'.', 'd.MM.y \'г\'.', 'd MMMM y \'г\'.', 'EEEE, d MMMM y \'г\'.'],
|
||||
['H:mm', 'H:mm:ss', 'H:mm:ss z', 'H:mm:ss zzzz'],
|
||||
['H:mm \'ч\'.', 'H:mm:ss \'ч\'.', 'H:mm:ss \'ч\'. z', 'H:mm:ss \'ч\'. zzzz'],
|
||||
[
|
||||
'{1}, {0}',
|
||||
,
|
||||
,
|
||||
],
|
||||
[',', ' ', ';', '%', '+', '-', 'E', '·', '‰', '∞', 'NaN', ':'],
|
||||
[',', ' ', ';', '%', '+', '-', 'E', '×', '‰', '∞', 'NaN', ':'],
|
||||
['#,##0.###', '#,##0%', '0.00 ¤', '#E0'], 'лв.', 'Български лев', function(n: number):
|
||||
number {
|
||||
if (n === 1) return 1;
|
||||
|
@ -44,11 +44,8 @@ export default [
|
||||
'নভেম্বর', 'ডিসেম্বর'
|
||||
],
|
||||
],
|
||||
[
|
||||
['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'],
|
||||
,
|
||||
],
|
||||
0, [0, 0], ['d/M/yy', 'd MMM, y', 'd MMMM, y', 'EEEE, d MMMM, y'],
|
||||
[['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'], , ['খ্রিস্টপূর্ব', 'খ্রীষ্টাব্দ']], 0, [0, 0],
|
||||
['d/M/yy', 'd MMM, y', 'd MMMM, y', 'EEEE, d MMMM, y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -44,11 +44,8 @@ export default [
|
||||
'নভেম্বর', 'ডিসেম্বর'
|
||||
],
|
||||
],
|
||||
[
|
||||
['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'],
|
||||
,
|
||||
],
|
||||
5, [6, 0], ['d/M/yy', 'd MMM, y', 'd MMMM, y', 'EEEE, d MMMM, y'],
|
||||
[['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'], , ['খ্রিস্টপূর্ব', 'খ্রীষ্টাব্দ']], 5, [6, 0],
|
||||
['d/M/yy', 'd MMM, y', 'd MMMM, y', 'EEEE, d MMMM, y'],
|
||||
['h:mm a', 'h:mm:ss a', 'h:mm:ss a z', 'h:mm:ss a zzzz'],
|
||||
[
|
||||
'{1} {0}',
|
||||
|
@ -18,19 +18,19 @@ export default [
|
||||
,
|
||||
[
|
||||
['н', 'п', 'у', 'с', 'ч', 'п', 'с'], ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
|
||||
['недеља', 'понедељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
|
||||
['недјеља', 'понедјељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
|
||||
['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб']
|
||||
],
|
||||
,
|
||||
[
|
||||
['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о', 'н', 'д'],
|
||||
['јан', 'феб', 'мар', 'апр', 'мај', 'јун', 'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
|
||||
['јан', 'феб', 'мар', 'апр', 'мај', 'јун', 'јул', 'ауг', 'сеп', 'окт', 'нов', 'дец'],
|
||||
[
|
||||
'јануар', 'фебруар', 'март', 'април', 'мај', 'јуни', 'јули', 'август', 'септембар', 'октобар',
|
||||
'јануар', 'фебруар', 'март', 'април', 'мај', 'јуни', 'јули', 'аугуст', 'септембар', 'октобар',
|
||||
'новембар', 'децембар'
|
||||
]
|
||||
],
|
||||
, [['п.н.е.', 'н.е.'], ['п. н. е.', 'н. е.'], ['Пре нове ере', 'Нове ере']], 1, [6, 0],
|
||||
, [['п.н.е.', 'н.е.'], ['п. н. е.', 'н. е.'], ['прије нове ере', 'нове ере']], 1, [6, 0],
|
||||
['d.M.yy.', 'dd.MM.y.', 'dd. MMMM y.', 'EEEE, dd. MMMM y.'],
|
||||
['HH:mm', 'HH:mm:ss', 'HH:mm:ss z', 'HH:mm:ss zzzz'],
|
||||
[
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user