@@ -2,6 +2,7 @@ import * as d from '../../declarations';
22import { dashToPascalCase } from '../../util/helpers' ;
33import { MEMBER_TYPE } from '../../util/constants' ;
44import { isDocsPublic } from '../util' ;
5+ import { OutputTargetAngular } from '../../declarations' ;
56
67
78export async function generateAngularProxies ( config : d . Config , compilerCtx : d . CompilerCtx , cmpRegistry : d . ComponentRegistry ) {
@@ -13,6 +14,17 @@ export async function generateAngularProxies(config: d.Config, compilerCtx: d.Co
1314 } ) ) ;
1415}
1516
17+ async function angularDirectiveProxyOutput ( config : d . Config , compilerCtx : d . CompilerCtx , outputTarget : d . OutputTargetAngular , cmpRegistry : d . ComponentRegistry ) {
18+ const components = getComponents ( outputTarget . excludeComponents , cmpRegistry ) ;
19+
20+ await Promise . all ( [
21+ generateProxies ( config , compilerCtx , components , outputTarget ) ,
22+ generateAngularArray ( config , compilerCtx , components , outputTarget ) ,
23+ generateAngularUtils ( compilerCtx , outputTarget )
24+ ] ) ;
25+
26+ config . logger . debug ( `generated angular directives: ${ outputTarget . directivesProxyFile } ` ) ;
27+ }
1628
1729function getComponents ( excludeComponents : string [ ] , cmpRegistry : d . ComponentRegistry ) : d . ComponentMeta [ ] {
1830 return Object . keys ( cmpRegistry )
@@ -25,124 +37,34 @@ function getComponents(excludeComponents: string[], cmpRegistry: d.ComponentRegi
2537 } ) ;
2638}
2739
28- async function angularDirectiveProxyOutput ( config : d . Config , compilerCtx : d . CompilerCtx , outputTarget : d . OutputTargetAngular , cmpRegistry : d . ComponentRegistry ) {
29- const components = getComponents ( outputTarget . excludeComponents , cmpRegistry ) ;
30- const useDirectives = outputTarget . useDirectives ;
31- const { hasOutputs, proxies } = generateProxies ( components , useDirectives ) ;
32-
33- const auxFunctions : string [ ] = [
34- inputsAuxFunction ( ) ,
35- outputsAuxFunction ( ) ,
36- methodsAuxFunction ( )
37- ] ;
38- const angularImports = [
39- 'ElementRef'
40- ] ;
41-
42- if ( components . length > 0 ) {
43- if ( useDirectives ) {
44- angularImports . push ( 'Directive' ) ;
45- } else {
46- angularImports . push ( 'Component' ) ;
47- angularImports . push ( 'ChangeDetectorRef' ) ;
48- }
49- }
50-
51- if ( hasOutputs ) {
52- angularImports . push ( 'EventEmitter' ) ;
53- }
40+ async function generateProxies ( config : d . Config , compilerCtx : d . CompilerCtx , components : d . ComponentMeta [ ] , outputTarget : OutputTargetAngular ) {
41+ const proxies = getProxies ( components ) ;
5442
55- const imports = `
56- ${ hasOutputs ? `import { fromEvent } from 'rxjs';` : '' }
57- import { ${ angularImports . sort ( ) . join ( ', ' ) } } from '@angular/core';
58- ` ;
43+ const imports = `/* tslint:disable */
44+ /* auto-generated angular directive proxies */
45+ import { Component, ElementRef, ChangeDetectorRef, EventEmitter } from '@angular/core';` ;
5946
6047 const sourceImports = ! outputTarget . componentCorePackage ? ''
6148 : `type StencilComponents<T extends keyof StencilElementInterfaces> = StencilElementInterfaces[T];` ;
6249
6350 const final : string [ ] = [
64- '/* tslint:disable */' ,
65- '/* auto-generated angular directive proxies */' ,
6651 imports ,
52+ getProxyUtils ( config , outputTarget ) ,
6753 sourceImports ,
68- auxFunctions . join ( '\n' ) ,
6954 proxies ,
7055 ] ;
7156
7257 const finalText = final . join ( '\n' ) + '\n' ;
7358 await compilerCtx . fs . writeFile ( outputTarget . directivesProxyFile , finalText ) ;
74- if ( outputTarget . directivesArrayFile ) {
75- const proxyPath = relativeImport ( config , outputTarget . directivesArrayFile , outputTarget . directivesProxyFile ) ;
76- const a = angularArray ( components , proxyPath ) ;
77- await compilerCtx . fs . writeFile ( outputTarget . directivesArrayFile , a ) ;
78- }
79- config . logger . debug ( `generated angular directives: ${ outputTarget . directivesProxyFile } ` ) ;
80- }
81-
82- function inputsAuxFunction ( ) {
83- return `
84- export function proxyInputs(Cmp: any, inputs: string[]) {
85- const Prototype = Cmp.prototype;
86- inputs.forEach(item => {
87- Object.defineProperty(Prototype, item, {
88- get() { return this.el[item]; },
89- set(val: any) { this.el[item] = val; },
90- });
91- });
92- }` ;
93- }
94-
95-
96- function outputsAuxFunction ( ) {
97- return `
98- export function proxyOutputs(instance: any, el: any, events: string[]) {
99- events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
100- }` ;
101- }
102-
103-
104- function methodsAuxFunction ( ) {
105- return `
106- export function proxyMethods(Cmp: any, methods: string[]) {
107- const Prototype = Cmp.prototype;
108- methods.forEach(methodName => {
109- Prototype[methodName] = function() {
110- const args = arguments;
111- return this.el.componentOnReady().then((el: any) => el[methodName].apply(el, args));
112- };
113- });
114- }
115- ` ;
11659}
11760
118- function generateProxies ( components : d . ComponentMeta [ ] , useDirectives : boolean ) {
119- let hasMethods = false ;
120- let hasOutputs = false ;
121- let hasInputs = false ;
122-
123- const lines = components . map ( cmpMeta => {
124- const proxy = generateProxy ( cmpMeta , useDirectives ) ;
125- if ( proxy . hasInputs ) {
126- hasInputs = true ;
127- }
128- if ( proxy . hasMethods ) {
129- hasMethods = true ;
130- }
131- if ( proxy . hasOutputs ) {
132- hasOutputs = true ;
133- }
134- return proxy . text ;
135- } ) ;
136-
137- return {
138- proxies : lines . join ( '\n' ) ,
139- hasInputs,
140- hasMethods,
141- hasOutputs
142- } ;
61+ function getProxies ( components : d . ComponentMeta [ ] ) {
62+ return components
63+ . map ( getProxy )
64+ . join ( '\n' ) ;
14365}
14466
145- function generateProxy ( cmpMeta : d . ComponentMeta , useDirectives : boolean ) {
67+ function getProxy ( cmpMeta : d . ComponentMeta ) {
14668 // Collect component meta
14769 const inputs = getInputs ( cmpMeta ) ;
14870 const outputs = getOutputs ( cmpMeta ) ;
@@ -154,32 +76,27 @@ function generateProxy(cmpMeta: d.ComponentMeta, useDirectives: boolean) {
15476 const hasMethods = methods . length > 0 ;
15577
15678 // Generate Angular @Directive
157- const decorator = useDirectives ? 'Directive' : 'Component' ;
15879 const directiveOpts = [
15980 `selector: \'${ cmpMeta . tagNameMeta } \'` ,
81+ `changeDetection: 0` ,
82+ `template: '<ng-content></ng-content>'`
16083 ] ;
161- if ( ! useDirectives ) {
162- directiveOpts . push (
163- `changeDetection: 0` ,
164- `template: '<ng-content></ng-content>'`
165- ) ;
166- }
16784 if ( inputs . length > 0 ) {
16885 directiveOpts . push ( `inputs: ['${ inputs . join ( `', '` ) } ']` ) ;
16986 }
17087
17188 const tagNameAsPascal = dashToPascalCase ( cmpMeta . tagNameMeta ) ;
17289 const lines = [ `
17390export declare interface ${ tagNameAsPascal } extends StencilComponents<'${ tagNameAsPascal } '> {}
174- @${ decorator } ({ ${ directiveOpts . join ( ', ' ) } })
91+ @Component ({ ${ directiveOpts . join ( ', ' ) } })
17592export class ${ tagNameAsPascal } {` ] ;
17693
17794 // Generate outputs
17895 outputs . forEach ( output => {
17996 lines . push ( ` ${ output } !: EventEmitter<CustomEvent>;` ) ;
18097 } ) ;
18198
182- lines . push ( ' el: HTMLElement' ) ;
99+ lines . push ( ' el: HTMLElement; ' ) ;
183100 lines . push ( ` constructor(c: ChangeDetectorRef, r: ElementRef) {
184101 c.detach();
185102 this.el = r.nativeElement;` ) ;
@@ -196,12 +113,7 @@ export class ${tagNameAsPascal} {`];
196113 lines . push ( `proxyInputs(${ tagNameAsPascal } , ['${ inputs . join ( `', '` ) } ']);` ) ;
197114 }
198115
199- return {
200- text : lines . join ( '\n' ) ,
201- hasInputs,
202- hasMethods,
203- hasOutputs
204- } ;
116+ return lines . join ( '\n' ) ;
205117}
206118
207119function getInputs ( cmpMeta : d . ComponentMeta ) {
@@ -224,24 +136,72 @@ function getMethods(cmpMeta: d.ComponentMeta) {
224136 } ) ;
225137}
226138
227-
228- function relativeImport ( config : d . Config , pathFrom : string , pathTo : string ) {
229- let relativePath = config . sys . path . relative ( config . sys . path . dirname ( pathFrom ) , config . sys . path . dirname ( pathTo ) ) ;
230- relativePath = relativePath === '' ? '.' : relativePath ;
231- return `${ relativePath } /${ config . sys . path . basename ( pathTo , '.ts' ) } ` ;
139+ function getProxyUtils ( config : d . Config , outputTarget : OutputTargetAngular ) {
140+ if ( ! outputTarget . directivesUtilsFile ) {
141+ return PROXY_UTILS . replace ( / e x p o r t f u n c t i o n / g, 'function' ) ;
142+ } else {
143+ const utilsPath = relativeImport ( config , outputTarget . directivesProxyFile , outputTarget . directivesUtilsFile ) ;
144+ return `import { proxyInputs, proxyMethods, proxyOutputs } from '${ utilsPath } ';\n` ;
145+ }
232146}
233147
234- function angularArray ( components : d . ComponentMeta [ ] , proxyPath : string ) {
148+ async function generateAngularArray ( config : d . Config , compilerCtx : d . CompilerCtx , components : d . ComponentMeta [ ] , outputTarget : OutputTargetAngular ) {
149+ if ( ! outputTarget . directivesArrayFile ) {
150+ return ;
151+ }
152+
153+ const proxyPath = relativeImport ( config , outputTarget . directivesArrayFile , outputTarget . directivesProxyFile ) ;
235154 const directives = components
236155 . map ( cmpMeta => dashToPascalCase ( cmpMeta . tagNameMeta ) )
237156 . map ( className => `d.${ className } ` )
238157 . join ( ',\n ' ) ;
239158
240- return `
159+ const c = `
241160import * as d from '${ proxyPath } ';
242161
243162export const DIRECTIVES = [
244- ${ directives }
163+ ${ directives }
245164];
246165` ;
166+ await compilerCtx . fs . writeFile ( outputTarget . directivesArrayFile , c ) ;
167+ }
168+
169+ async function generateAngularUtils ( compilerCtx : d . CompilerCtx , outputTarget : OutputTargetAngular ) {
170+ if ( outputTarget . directivesUtilsFile ) {
171+ await compilerCtx . fs . writeFile ( outputTarget . directivesUtilsFile , '/* tslint:disable */\n' + PROXY_UTILS ) ;
172+ }
173+ }
174+
175+ function relativeImport ( config : d . Config , pathFrom : string , pathTo : string ) {
176+ let relativePath = config . sys . path . relative ( config . sys . path . dirname ( pathFrom ) , config . sys . path . dirname ( pathTo ) ) ;
177+ relativePath = relativePath === '' ? '.' : relativePath ;
178+ return `${ relativePath } /${ config . sys . path . basename ( pathTo , '.ts' ) } ` ;
247179}
180+
181+ const PROXY_UTILS = `import { fromEvent } from 'rxjs';
182+
183+ export function proxyInputs(Cmp: any, inputs: string[]) {
184+ const Prototype = Cmp.prototype;
185+ inputs.forEach(item => {
186+ Object.defineProperty(Prototype, item, {
187+ get() { return this.el[item]; },
188+ set(val: any) { this.el[item] = val; },
189+ });
190+ });
191+ }
192+
193+ export function proxyMethods(Cmp: any, methods: string[]) {
194+ const Prototype = Cmp.prototype;
195+ methods.forEach(methodName => {
196+ Prototype[methodName] = function() {
197+ const args = arguments;
198+ return this.el.componentOnReady().then((el: any) => el[methodName].apply(el, args));
199+ };
200+ });
201+ }
202+
203+ export function proxyOutputs(instance: any, el: any, events: string[]) {
204+ events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
205+ }
206+ ` ;
207+
0 commit comments