From 861953c95c9d8a0d9a831ae02adc59ecef118a7d Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Tue, 28 Mar 2017 14:41:50 -0700 Subject: [PATCH] feat(aio): add LiveExampleComponent (#15544) --- aio/content/marketing/test.html | 49 +++- aio/src/app/embedded/embedded.module.ts | 6 +- .../live-example/live-example.component.html | 15 + .../live-example.component.spec.ts | 265 ++++++++++++++++++ .../live-example/live-example.component.ts | 166 +++++++++++ aio/src/app/shared/location.service.ts | 7 +- aio/src/assets/images/plunker/placeholder.png | Bin 7959 -> 7611 bytes 7 files changed, 495 insertions(+), 13 deletions(-) create mode 100644 aio/src/app/embedded/live-example/live-example.component.html create mode 100644 aio/src/app/embedded/live-example/live-example.component.spec.ts create mode 100644 aio/src/app/embedded/live-example/live-example.component.ts diff --git a/aio/content/marketing/test.html b/aio/content/marketing/test.html index 3a0c48a9fb..9a56e08e02 100644 --- a/aio/content/marketing/test.html +++ b/aio/content/marketing/test.html @@ -4,9 +4,11 @@

No linenums at code-tabs level

- class { - foo(param: string) {} -} + + class { + foo(param: string) {} + } + <h1>Heading</h1> { "key": "value" } @@ -14,9 +16,11 @@

linenums=true at code-tabs level

- class { - foo(param: string) {} -} + + class { + foo(param: string) {} + } + <h1>Heading</h1> { "key": "value" } @@ -24,9 +28,11 @@

No linenums at code-tabs level; linenums=true for HTML pane

- class { - foo(param: string) {} -} + + class { + foo(param: string) {} + } + <h1>Heading</h1> { "key": "value" } @@ -77,4 +83,27 @@ </hero-details> -

More text follows ...

\ No newline at end of file +

<live-example>

+ +

Plain live-example

+Try this . + +

live-example with title atty

+ + +

live-example with title body

+Try this great example + +

live-example with name

+ + +

live-example with spacey name and plnkr

+ + +

live-example with name and plnkr but no download

+ + +

live-example embedded with name and plnkr

+ + +

More text follows ...

diff --git a/aio/src/app/embedded/embedded.module.ts b/aio/src/app/embedded/embedded.module.ts index 588d6bf089..4d360ea1c2 100644 --- a/aio/src/app/embedded/embedded.module.ts +++ b/aio/src/app/embedded/embedded.module.ts @@ -17,12 +17,13 @@ import { ApiListComponent } from './api/api-list.component'; import { CodeExampleComponent } from './code/code-example.component'; import { CodeTabsComponent } from './code/code-tabs.component'; import { DocTitleComponent } from './doc-title.component'; +import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/live-example.component'; /** Components that can be embedded in docs * such as CodeExampleComponent, LiveExampleComponent,... */ export const embeddedComponents: any[] = [ - ApiListComponent, CodeExampleComponent, DocTitleComponent, CodeTabsComponent + ApiListComponent, CodeExampleComponent, DocTitleComponent, CodeTabsComponent, LiveExampleComponent ]; /** Injectable class w/ property returning components that can be embedded in docs */ @@ -34,7 +35,8 @@ export class EmbeddedComponents { imports: [ CommonModule, MdTabsModule ], declarations: [ embeddedComponents, - CodeComponent + CodeComponent, + EmbeddedPlunkerComponent ], providers: [ EmbeddedComponents, diff --git a/aio/src/app/embedded/live-example/live-example.component.html b/aio/src/app/embedded/live-example/live-example.component.html new file mode 100644 index 0000000000..33a53fabb4 --- /dev/null +++ b/aio/src/app/embedded/live-example/live-example.component.html @@ -0,0 +1,15 @@ + + {{title}} + + / download example + + +
+
+ +
+ {{title}} +

+ You can also download this example. +

+
diff --git a/aio/src/app/embedded/live-example/live-example.component.spec.ts b/aio/src/app/embedded/live-example/live-example.component.spec.ts new file mode 100644 index 0000000000..e966e231a6 --- /dev/null +++ b/aio/src/app/embedded/live-example/live-example.component.spec.ts @@ -0,0 +1,265 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Component, DebugElement, ElementRef } from '@angular/core'; +import { Location } from '@angular/common'; + +import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example.component'; + +const defaultTestPath = '/test'; + +describe('LiveExampleComponent', () => { + let hostComponent: HostComponent; + let liveExampleDe: DebugElement; + let liveExampleComponent: LiveExampleComponent; + let fixture: ComponentFixture; + let testPath: string; + let liveExampleContent: string; + + //////// test helpers //////// + + @Component({ + selector: 'aio-host-comp', + template: `` + }) + class HostComponent { } + + class TestLocation { + path() { return testPath; } + } + + function setHostTemplate(template: string) { + TestBed.overrideComponent(HostComponent, {set: {template}}); + } + + function testComponent(testFn: () => void) { + return TestBed + .compileComponents() + .then(() => { + fixture = TestBed.createComponent(HostComponent); + hostComponent = fixture.componentInstance; + liveExampleDe = fixture.debugElement.children[0]; + liveExampleComponent = liveExampleDe.componentInstance; + + // Copy the LiveExample's innerHTML (content) + // into the `liveExampleContent` property as the DocViewer does + liveExampleDe.nativeElement.liveExampleContent = liveExampleContent; + + fixture.detectChanges(); + }) + .then(testFn); + } + + //////// tests //////// + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ HostComponent, LiveExampleComponent, EmbeddedPlunkerComponent ], + providers: [ {provide: Location, useClass: TestLocation }] + }) + // Disable the `, + styles: [ 'iframe { min-height: 400px; }'] +}) +export class EmbeddedPlunkerComponent implements AfterViewInit { + @Input() src: string; + + @ViewChild('iframe') iframe: ElementRef; + + ngAfterViewInit() { + // DEVELOPMENT TESTING ONLY + // this.src = 'https://angular.io/resources/live-examples/quickstart/ts/eplnkr.html'; + + if (this.iframe) { + // security: the `src` is always authored by the documentation team + // and is considered to be safe + this.iframe.nativeElement.src = this.src; + } + } +} diff --git a/aio/src/app/shared/location.service.ts b/aio/src/app/shared/location.service.ts index 2cf2a21eb3..4990a0e453 100644 --- a/aio/src/app/shared/location.service.ts +++ b/aio/src/app/shared/location.service.ts @@ -90,8 +90,13 @@ export class LocationService { return true; } - // check for external link + // don't navigate if external link or zip const { pathname, search, hash } = anchor; + + if (anchor.getAttribute('download') != null) { + return true; // let the download happen + } + const relativeUrl = pathname + search + hash; this.urlParser.href = relativeUrl; if (anchor.href !== this.urlParser.href) { diff --git a/aio/src/assets/images/plunker/placeholder.png b/aio/src/assets/images/plunker/placeholder.png index 585cd11696d30c8ceb2b3808dfc23d193bab4ee0..54c3369ee247c58ed0c5d8af8d5f4099ec914f7e 100644 GIT binary patch literal 7611 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 literal 7959 zcmbVxcQjn>yY`4E5sco==p<@LbfXi|qeTmm1VQv}2tjnCiv$xb6A?tO5#6Xm^xj5| zHZ$4~@=4y``+eu1@2qvsTDx5PZqN1Xz3*$UXYCjRJxvNS7BT<;K%sSC?I8d_2mt^H z4oR;JfN34XZvX(aprxj4>`$;W8|gQ@&EAbUucPa3?s#f%Z{Hm*C$^BcQ8U`ji(1RB z-;8gc_Q_(c&rSU}Q`2EM9AnL2d6;H%>vk`v+aCMeBEPNutFA!4i{C|c`!h$c?1?q_ z>~G$Ti;FXTA(PSaY`Oc_PMVCk?V-)+S>Px=?Ml|&-@Gc(uOz^nJYa-vV)`97X*xTK z6qp3V`A*OR{Xs5jpEWaNf{O><4z|JNiN4}p>IeH@w8@+CN1&gEoON{12NC!+LeA!? z%k)Tl9S(DBPJTAzxHxU&&Tm0?tHSA2z9ge&Th{nH{Jvw;4`7VnFSE$7)GF8j+#8Bl zk2v90nZ4<2KP3Bg>~*7ZlXI(`6%;IruSNRD<^#Ay-60gw(^ko0%*4`B1TOCpB^0^W zCo|0E>GIF`Xvi$yPO|`nCTqS+CI`ym={gMf%+d^>eyOv46fD-jz8kEeSG`4M z7#!0tsbG3hiRW3~MpttA3smYr;^JUyUO{yT`C<^19noXz?bEdIxgjl;$YSrhqVY5&K0d5W*^XQ& z{G8US2mTn_vCp!@UZ_e1jSJQqUX^zkoOoK7ld>*$Lg>A@VK?u+W9$N`s;PjYLdL z!Xo+l=$o^Q>y)z0g}qgu2_FOKzcjLJFzkH5∈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