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

Commit 2c18098

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. - [x] Remove useless imports.
1 parent 5079eee commit 2c18098

34 files changed

+377
-105
lines changed

app-shell/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@angular/platform-browser-dynamic": "^2.0.0-rc.6",
2525
"es6-shim": "^0.35.0",
2626
"reflect-metadata": "0.1.3",
27-
"rxjs": "5.0.0-beta.11",
27+
"rxjs": "^5.0.0-beta.11",
2828
"systemjs": "0.19.26",
2929
"zone.js": "^0.6.17"
3030
},
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Provider} from '@angular/core';
2+
3+
import { IS_PRERENDER } from './is-prerender.service';
4+
import { TemplateVisibilityStrategy } from './template-visibility-strategy';
5+
import { TemplateCommentStrategy } from './template-comment-strategy';
6+
7+
export const APP_SHELL_RUNTIME_PROVIDERS: Provider[] = [
8+
{
9+
provide: IS_PRERENDER,
10+
useValue: false
11+
},
12+
{
13+
provide: TemplateVisibilityStrategy,
14+
useClass: TemplateCommentStrategy
15+
}
16+
];
17+
18+
export const APP_SHELL_BUILD_PROVIDERS: Provider[] = [
19+
{
20+
provide: IS_PRERENDER,
21+
useValue: true
22+
},
23+
{
24+
provide: TemplateVisibilityStrategy,
25+
useClass: TemplateCommentStrategy
26+
}
27+
];

app-shell/src/app/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { Type, NgModule, ModuleWithProviders } from '@angular/core';
22
import { ShellRender } from './shell-render.directive';
33
import { ShellNoRender } from './shell-no-render.directive';
4-
import { IS_PRERENDER } from './is-prerender.service';
5-
import { APP_SHELL_RUNTIME_PROVIDERS, APP_SHELL_BUILD_PROVIDERS } from './is-prerender.service';
4+
import { APP_SHELL_RUNTIME_PROVIDERS, APP_SHELL_BUILD_PROVIDERS } from './app-shell-providers';
65

7-
export * from './is-prerender.service';
6+
export * from './app-shell-providers';
7+
export * from './template-visibility-strategy';
8+
export * from './app-shell-providers';
89
export * from './shell-no-render.directive';
910
export * from './shell-render.directive';
11+
export * from './is-prerender.service';
1012

1113
const APP_SHELL_DIRECTIVES: Type<any>[] = [
1214
ShellRender,
@@ -25,4 +27,3 @@ export class AppShellModule {
2527
};
2628
}
2729
}
28-
Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
import { OpaqueToken, Provider } from '@angular/core';
1+
import { OpaqueToken } from '@angular/core';
22

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

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import {
66
} from '@angular/core/testing';
77
import { Component } from '@angular/core';
88

9-
import { ShellNoRender } from './shell-no-render.directive';
10-
import { APP_SHELL_RUNTIME_PROVIDERS, APP_SHELL_BUILD_PROVIDERS } from './is-prerender.service';
119
import {
12-
AppShellModule
10+
AppShellModule,
11+
APP_SHELL_RUNTIME_PROVIDERS,
12+
APP_SHELL_BUILD_PROVIDERS
1313
} from './index';
14+
import { ShellNoRender } from './shell-no-render.directive';
1415

1516
@Component({
1617
selector: 'test-component',
@@ -24,9 +25,9 @@ describe('ShellNoRender Directive', () => {
2425

2526
beforeEach(() => {
2627
TestBed.configureTestingModule({
27-
imports: [AppShellModule],
28-
providers: [APP_SHELL_BUILD_PROVIDERS],
29-
declarations: [TestComponent]
28+
imports: [AppShellModule],
29+
providers: [APP_SHELL_BUILD_PROVIDERS],
30+
declarations: [TestComponent]
3031
});
3132
TestBed.compileComponents();
3233
});
@@ -44,9 +45,9 @@ describe('ShellNoRender Directive', () => {
4445

4546
beforeEach(() => {
4647
TestBed.configureTestingModule({
47-
imports: [AppShellModule],
48-
providers: [APP_SHELL_RUNTIME_PROVIDERS],
49-
declarations: [TestComponent]
48+
imports: [AppShellModule],
49+
providers: [APP_SHELL_RUNTIME_PROVIDERS],
50+
declarations: [TestComponent]
5051
});
5152
TestBed.compileComponents();
5253
});
@@ -58,5 +59,13 @@ describe('ShellNoRender Directive', () => {
5859
expect(fixture.debugElement.childNodes[0].nativeNode.textContent).toBe('template bindings={}');
5960
expect(fixture.debugElement.childNodes[1].nativeNode.textContent).toBe('Rendered');
6061
});
62+
63+
it('should set "shellNoRender" attribute', () => {
64+
const fixture = TestBed.createComponent(TestComponent);
65+
fixture.detectChanges();
66+
expect(fixture.debugElement.childNodes.length).toBe(2);
67+
expect(fixture.debugElement.childNodes[1].nativeNode.getAttribute('shellNoRender')).toBe('');
68+
});
69+
6170
});
6271
});
Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
1-
import { Directive, Inject, OnInit, ViewContainerRef, TemplateRef } from '@angular/core';
1+
import { Directive, Inject, OnInit, ViewContainerRef, TemplateRef, AfterViewInit } from '@angular/core';
22

3+
import { TemplateVisibilityStrategy } from './template-visibility-strategy';
34
import { IS_PRERENDER } from './is-prerender.service';
45

5-
@Directive({selector: '[shellNoRender]'})
6-
export class ShellNoRender implements OnInit {
6+
const MARKER = 'shellNoRender';
7+
8+
@Directive({
9+
selector: `[${MARKER}]`
10+
})
11+
export class ShellNoRender implements OnInit, AfterViewInit {
712
constructor(
813
private _viewContainer: ViewContainerRef,
914
private _templateRef: TemplateRef<Object>,
15+
private _templateVisibilityStrategy: TemplateVisibilityStrategy,
1016
@Inject(IS_PRERENDER) private _isPrerender: boolean) {
1117
}
1218

1319
ngOnInit () {
20+
const view = this._viewContainer.createEmbeddedView(this._templateRef);
21+
this._templateVisibilityStrategy.setRootNodes(MARKER, view.rootNodes.pop());
22+
}
23+
24+
ngAfterViewInit() {
1425
if (this._isPrerender) {
26+
this._templateVisibilityStrategy.hide(MARKER);
1527
this._viewContainer.clear();
1628
} else {
17-
this._viewContainer.createEmbeddedView(this._templateRef);
29+
this._templateVisibilityStrategy.show(MARKER);
1830
}
1931
}
2032
}
33+

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ export interface ASTNode {
99
parentNode?: ASTNode;
1010
nodeName: string;
1111
value?: string;
12+
data?: string;
1213
}
13-
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export * from './ast-node';
2-

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
};

app-shell/src/app/shell-parser/node-matcher/css-node-matcher.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import {
2-
inject
3-
} from '@angular/core/testing';
41
import { ASTNode } from '../ast';
52
import { CssSelector } from './css-selector';
63
import { CssNodeMatcher } from './css-node-matcher';

app-shell/src/app/shell-parser/node-matcher/css-selector/css-selector.spec.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import {
2-
inject
3-
} from '@angular/core/testing';
41
import { CssSelector } from './css-selector';
52

63
describe('CssSelector', () => {
@@ -52,7 +49,5 @@ describe('CssSelector', () => {
5249
expect(result.elementId).toBe('baz');
5350
expect(result.classNames).toEqual(['foo', 'qux']);
5451
});
55-
5652
});
5753
});
58-
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export * from './css-selector';
2-

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ import {ASTNode} from '../ast';
33
export abstract class NodeMatcher {
44
abstract match(node: ASTNode): boolean;
55
}
6-
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/node-visitor.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ export abstract class NodeVisitor {
1616
} else {
1717
return null;
1818
}
19-
})
19+
});
2020
}
21-
2221
}
23-

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import {
2-
inject
3-
} from '@angular/core/testing';
4-
51
import {ASTNode} from '../../ast';
62
import {MockWorkerScope, MockResponse} from '../../testing';
73
import {InlineStyleResourceInlineVisitor} from './';

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import {ASTNode, ASTAttribute} from '../../ast';
22
import {ResourceInlineVisitor} from './resource-inline-visitor';
3-
import {WorkerScope} from '../../context';
4-
5-
const URL_REGEXP = /:\s+url\(['"]?(.*?)['"]?\)/gmi;
63

74
export class InlineStyleResourceInlineVisitor extends ResourceInlineVisitor {
85

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {ASTNode} from '../../ast';
21
import {NodeVisitor} from '../node-visitor';
32
import {WorkerScope} from '../../context';
43

@@ -13,8 +12,7 @@ export abstract class ResourceInlineVisitor extends NodeVisitor {
1312
inlineAssets(style: string) {
1413
let urls = this.getImagesUrls(style);
1514
urls = urls.filter((url: string, idx: number) => urls.indexOf(url) === idx);
16-
return this.processInline(urls, style)
17-
.then((content: string) => content);
15+
return this.processInline(urls, style);
1816
}
1917

2018
protected getImagesUrls(styles: string): string[] {
@@ -55,6 +53,4 @@ export abstract class ResourceInlineVisitor extends NodeVisitor {
5553
img ? content.replace(new RegExp(urls[idx], 'g'), img) : content, styles);
5654
});
5755
}
58-
5956
}
60-

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import {
2-
inject
3-
} from '@angular/core/testing';
4-
51
import {ASTNode} from '../../ast';
62
import {MockWorkerScope, MockResponse} from '../../testing';
73
import {StylesheetResourceInlineVisitor} from './';
@@ -193,4 +189,3 @@ describe('ResourceInlineVisitor', () => {
193189
});
194190

195191
});
196-

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,4 @@ export class StylesheetResourceInlineVisitor extends ResourceInlineVisitor {
1717
}
1818
return Promise.resolve(node);
1919
}
20-
2120
}
22-

0 commit comments

Comments
 (0)