Skip to content
This repository was archived by the owner on Oct 12, 2021. It is now read-only.

Commit 9e2c349

Browse files
committed
feat(AppShell): shellRender and shellNoRender attributes and implement different stripping strategies
- [x] Make the shell-related directives add `shellRender` and `shellNoRender` attributes. - [x] Encapsulate the "hiding", "showing" element logic into a service which is injected with DI and can its provider can be overridden. - [x] Add visitor which finds App Shell related comments in templates and processes them.
1 parent e0775d4 commit 9e2c349

20 files changed

+354
-33
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { IS_PRERENDER } from './is-prerender.service';
2+
import { TemplateVisibilityStrategy } from './template-visibility-strategy';
3+
import { TemplateCommentStrategy } from './template-comment-strategy';
4+
5+
export const APP_SHELL_RUNTIME_PROVIDERS: any[] = [
6+
{
7+
provide: IS_PRERENDER,
8+
useValue: false
9+
},
10+
{
11+
provide: TemplateVisibilityStrategy,
12+
useClass: TemplateCommentStrategy
13+
}
14+
];
15+
16+
export const APP_SHELL_BUILD_PROVIDERS: any[] = [
17+
{
18+
provide: IS_PRERENDER,
19+
useValue: true
20+
},
21+
{
22+
provide: TemplateVisibilityStrategy,
23+
useClass: TemplateCommentStrategy
24+
}
25+
];

app-shell/src/app/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Type } from '@angular/core';
22
import { ShellRender } from './shell-render.directive';
33
import { ShellNoRender } from './shell-no-render.directive';
44

5+
export * from './app-shell-providers';
6+
export * from './template-visibility-strategy';
57
export * from './is-prerender.service';
68
export * from './shell-no-render.directive';
79
export * from './shell-render.directive';

app-shell/src/app/is-prerender.service.spec.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ import {
66
inject
77
} from '@angular/core/testing';
88
import {
9-
APP_SHELL_BUILD_PROVIDERS,
10-
APP_SHELL_RUNTIME_PROVIDERS,
119
IS_PRERENDER
1210
} from './is-prerender.service';
1311

12+
import {
13+
APP_SHELL_BUILD_PROVIDERS,
14+
APP_SHELL_RUNTIME_PROVIDERS,
15+
} from './app-shell-providers';
16+
1417
describe('IsPrerender Service', () => {
1518
describe('prerender', () => {
1619
beforeEachProviders(() => [APP_SHELL_BUILD_PROVIDERS]);
Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
11
import {OpaqueToken, provide, Provider} from '@angular/core';
22

33
export const IS_PRERENDER = new OpaqueToken('IsPrerender');
4-
5-
export const APP_SHELL_RUNTIME_PROVIDERS: Provider[] = [
6-
provide(IS_PRERENDER, {
7-
useValue: false
8-
})
9-
];
10-
11-
export const APP_SHELL_BUILD_PROVIDERS: Provider[] = [
12-
provide(IS_PRERENDER, {
13-
useValue: true
14-
})
15-
];

app-shell/src/app/shell-no-render.directive.spec.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { ShellNoRender } from './shell-no-render.directive';
1212
import {
1313
APP_SHELL_BUILD_PROVIDERS,
1414
APP_SHELL_RUNTIME_PROVIDERS
15-
} from './is-prerender.service';
15+
} from './app-shell-providers';
1616

1717
@Component({
1818
selector: 'test-component',
@@ -28,8 +28,10 @@ describe('ShellNoRender Directive', () => {
2828
it('should NOT render the element', async(inject([TestComponentBuilder], (tcb:TestComponentBuilder) => {
2929
return tcb.createAsync(TestComponent).then((fixture: ComponentFixture<TestComponent>) => {
3030
fixture.detectChanges();
31-
expect(fixture.debugElement.childNodes.length).toBe(1);
32-
expect(fixture.debugElement.childNodes[0].nativeNode.textContent).toBe('template bindings={}');
31+
const childNodes = fixture.debugElement.nativeElement.childNodes;
32+
expect(childNodes.length).toBe(2);
33+
expect(childNodes[0].textContent).toBe('template bindings={}');
34+
expect(childNodes[1].textContent).toBe('shellNoRender(<div>Rendered</div>)');
3335
});
3436
})));
3537
});
@@ -46,5 +48,14 @@ describe('ShellNoRender Directive', () => {
4648
expect(fixture.debugElement.childNodes[1].nativeNode.textContent).toBe('Rendered');
4749
});
4850
})));
51+
52+
it('should set "shellNoRender" attribute', async(inject([TestComponentBuilder], (tcb:TestComponentBuilder) => {
53+
return tcb.createAsync(TestComponent).then((fixture: ComponentFixture<TestComponent>) => {
54+
fixture.detectChanges();
55+
expect(fixture.debugElement.childNodes.length).toBe(2);
56+
expect(fixture.debugElement.childNodes[1].nativeNode.getAttribute('shellNoRender')).toBe('');
57+
});
58+
})));
59+
4960
});
5061
});
Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
1-
import { Directive, Inject, OnInit, ViewContainerRef, TemplateRef } from '@angular/core';
1+
import { Directive, Inject, OnInit, ViewContainerRef, TemplateRef, Renderer, AfterViewInit } from '@angular/core';
2+
import { getDOM } from '@angular/platform-browser/src/dom/dom_adapter';
23

3-
import {IS_PRERENDER} from './is-prerender.service';
4+
import { TemplateVisibilityStrategy } from './template-visibility-strategy';
5+
import { IS_PRERENDER } from './is-prerender.service';
46

57
@Directive({selector: '[shellNoRender]'})
6-
export class ShellNoRender implements OnInit {
8+
export class ShellNoRender implements OnInit, AfterViewInit {
79
constructor(
810
private _viewContainer: ViewContainerRef,
911
private _templateRef: TemplateRef<Object>,
12+
private _templateVisibilityStrategy: TemplateVisibilityStrategy,
1013
@Inject(IS_PRERENDER) private _isPrerender: boolean) {
1114
}
1215

1316
ngOnInit () {
17+
const view = this._viewContainer.createEmbeddedView(this._templateRef);
18+
this._templateVisibilityStrategy.initialize(view.rootNodes.pop(), 'shellNoRender');
19+
}
20+
21+
ngAfterViewInit() {
1422
if (this._isPrerender) {
23+
this._templateVisibilityStrategy.hide();
1524
this._viewContainer.clear();
1625
} else {
17-
this._viewContainer.createEmbeddedView(this._templateRef);
26+
this._templateVisibilityStrategy.show();
1827
}
1928
}
29+
2030
}

app-shell/src/app/shell-parser/ast/ast-node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export interface ASTNode {
99
parentNode?: ASTNode;
1010
nodeName: string;
1111
value?: string;
12+
data?: string;
1213
}
1314

app-shell/src/app/shell-parser/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export type RouteDefinition = string;
33
const SHELL_PARSER_CACHE_NAME = 'mobile-toolkit:app-shell';
44
const APP_SHELL_URL = './app_shell.html';
55
const NO_RENDER_CSS_SELECTOR = '[shellNoRender]';
6+
const RENDER_MARKER = 'shellRender';
67
const ROUTE_DEFINITIONS: RouteDefinition[] = [];
78
const INLINE_IMAGES: string[] = ['png', 'svg', 'jpg'];
89

@@ -13,6 +14,7 @@ export interface ShellParserConfig {
1314
APP_SHELL_URL?: string;
1415
SHELL_PARSER_CACHE_NAME?: string;
1516
NO_RENDER_CSS_SELECTOR?: string;
17+
RENDER_MARKER?: string;
1618
ROUTE_DEFINITIONS?: RouteDefinition[];
1719
INLINE_IMAGES?: string[];
1820
}
@@ -21,6 +23,7 @@ export const SHELL_PARSER_DEFAULT_CONFIG: ShellParserConfig = {
2123
SHELL_PARSER_CACHE_NAME,
2224
APP_SHELL_URL,
2325
NO_RENDER_CSS_SELECTOR,
26+
RENDER_MARKER,
2427
ROUTE_DEFINITIONS,
2528
INLINE_IMAGES
2629
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './node-visitor';
22
export * from './resource-inline';
33
export * from './template-strip-visitor';
4+
export * from './template-recover-visitor';
45

app-shell/src/app/shell-parser/node-visitor/resource-inline/resource-inline-visitor.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ export abstract class ResourceInlineVisitor extends NodeVisitor {
1313
inlineAssets(style: string) {
1414
let urls = this.getImagesUrls(style);
1515
urls = urls.filter((url: string, idx: number) => urls.indexOf(url) === idx);
16-
return this.processInline(urls, style)
17-
.then((content: string) => content);
16+
return this.processInline(urls, style);
1817
}
1918

2019
protected getImagesUrls(styles: string): string[] {

0 commit comments

Comments
 (0)