Skip to content

Commit 373b152

Browse files
committed
Refactoring readTemplate and readStyle to use Maybe<T>
1 parent ba0f67f commit 373b152

File tree

2 files changed

+173
-174
lines changed

2 files changed

+173
-174
lines changed

src/angular/metadataReader.ts

+120-129
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,22 @@ import {logger} from '../util/logger';
88

99
import {Config} from './config';
1010

11-
import {DirectiveMetadata, ComponentMetadata, CodeWithSourceMap, TemplateMetadata} from './metadata';
12-
import {Maybe, unwrapFirst, ifTrue,} from '../util/function';
1311
import {
14-
callExpression, withIdentifier, hasProperties,
15-
isSimpleTemplateString, getStringInitializerFromProperty, decoratorArgument
12+
DirectiveMetadata, ComponentMetadata, CodeWithSourceMap, TemplateMetadata, StylesMetadata,
13+
StyleMetadata
14+
} from './metadata';
15+
import {Maybe, unwrapFirst, ifTrue, listToMaybe,} from '../util/function';
16+
import {
17+
callExpression, withIdentifier, hasProperties,
18+
isSimpleTemplateString, getStringInitializerFromProperty, decoratorArgument
1619
} from '../util/astQuery';
1720
import {getTemplate, getInlineStyle} from '../util/ngQuery';
1821

1922
const normalizeTransformed = (t: CodeWithSourceMap) => {
20-
if (!t.map) {
21-
t.source = t.code;
22-
}
23-
return t;
23+
if (!t.map) {
24+
t.source = t.code;
25+
}
26+
return t;
2427
};
2528

2629

@@ -29,127 +32,115 @@ const normalizeTransformed = (t: CodeWithSourceMap) => {
2932
*/
3033
export class MetadataReader {
3134

32-
constructor(private _fileResolver: FileResolver, private _urlResolver?: AbstractResolver) {
33-
this._urlResolver = this._urlResolver || new UrlResolver(new PathResolver());
34-
}
35-
36-
read(d: ts.ClassDeclaration): DirectiveMetadata {
37-
let componentMetadata = unwrapFirst(
38-
(d.decorators || ([] as ts.Decorator[])).map((dec: ts.Decorator) => {
39-
return Maybe.lift(dec).bind(callExpression)
40-
.bind(withIdentifier('Component'))
41-
.fmap(() => this.readComponentMetadata(d, dec));
42-
}));
43-
44-
let directiveMetadata = unwrapFirst(
45-
(d.decorators || ([] as ts.Decorator[])).map((dec: ts.Decorator) =>
46-
Maybe.lift(dec)
47-
.bind(callExpression)
48-
.bind(withIdentifier('Directive'))
49-
.fmap(() => this.readDirectiveMetadata(d, dec))
50-
));
51-
52-
return directiveMetadata || componentMetadata || undefined;
53-
}
54-
55-
readDirectiveMetadata(d: ts.ClassDeclaration, dec: ts.Decorator): DirectiveMetadata {
56-
57-
const selector = this.getDecoratorArgument(dec)
58-
.bind(expr => getStringInitializerFromProperty('selector', expr.properties))
59-
.fmap(initializer => initializer.text);
60-
61-
return Object.assign(new DirectiveMetadata(), {
62-
controller: d,
63-
decorator: dec,
64-
selector: selector.unwrap(),
65-
});
66-
}
67-
68-
readComponentTemplateMetadata(dec: ts.Decorator, external: MetadataUrls): TemplateMetadata {
69-
const template_M = getTemplate(dec)
70-
.fmap(inlineTemplate => {
71-
const transformed = normalizeTransformed(Config.transformTemplate(inlineTemplate.text, null, dec));
72-
return {
73-
template: transformed,
74-
url: null,
75-
node: inlineTemplate,
76-
};
77-
});
78-
79-
if (template_M.isSomething) {
80-
return template_M.unwrap();
81-
} else {
82-
// TODO: Refactoring this requires adding seem to fileResolver
83-
if (external.templateUrl) {
84-
try {
85-
const template = this._fileResolver.resolve(external.templateUrl);
86-
const transformed = normalizeTransformed(Config.transformTemplate(template, external.templateUrl, dec));
87-
return {
88-
template: transformed,
89-
url: external.templateUrl,
90-
node: null
91-
};
92-
} catch (e) {
93-
logger.info('Cannot read the external template ' + external.templateUrl);
94-
}
95-
}
35+
constructor(private _fileResolver: FileResolver, private _urlResolver?: AbstractResolver) {
36+
this._urlResolver = this._urlResolver || new UrlResolver(new PathResolver());
37+
}
38+
39+
read(d: ts.ClassDeclaration): DirectiveMetadata {
40+
let componentMetadata = unwrapFirst(
41+
(d.decorators || ([] as ts.Decorator[])).map((dec: ts.Decorator) => {
42+
return Maybe.lift(dec).bind(callExpression)
43+
.bind(withIdentifier('Component'))
44+
.fmap(() => this.readComponentMetadata(d, dec));
45+
}));
46+
47+
let directiveMetadata = unwrapFirst(
48+
(d.decorators || ([] as ts.Decorator[])).map((dec: ts.Decorator) =>
49+
Maybe.lift(dec)
50+
.bind(callExpression)
51+
.bind(withIdentifier('Directive'))
52+
.fmap(() => this.readDirectiveMetadata(d, dec))
53+
));
54+
55+
return directiveMetadata || componentMetadata || undefined;
56+
}
57+
58+
protected readDirectiveMetadata(d: ts.ClassDeclaration, dec: ts.Decorator): DirectiveMetadata {
59+
const selector = this.getDecoratorArgument(dec)
60+
.bind(expr => getStringInitializerFromProperty('selector', expr.properties))
61+
.fmap(initializer => initializer.text);
62+
63+
return Object.assign(new DirectiveMetadata(), {
64+
controller: d,
65+
decorator: dec,
66+
selector: selector.unwrap(),
67+
});
68+
}
69+
70+
protected readComponentMetadata(d: ts.ClassDeclaration, dec: ts.Decorator) {
71+
const expr = this.getDecoratorArgument(dec);
72+
const directiveMetadata = this.readDirectiveMetadata(d, dec);
73+
74+
const external_M = expr.fmap(() => this._urlResolver.resolve(dec));
75+
76+
const template_M: Maybe<TemplateMetadata> = external_M.bind(external =>
77+
this.readComponentTemplateMetadata(dec, external));
78+
const style_M: Maybe<StylesMetadata> = external_M.bind(external =>
79+
this.readComponentStylesMetadata(dec, external));
80+
81+
return Object.assign(new ComponentMetadata(), directiveMetadata, {
82+
template: template_M.unwrap(),
83+
styles: style_M.unwrap(),
84+
});
85+
}
86+
87+
protected getDecoratorArgument(decorator: ts.Decorator): Maybe<ts.ObjectLiteralExpression> {
88+
return decoratorArgument(decorator)
89+
.bind(ifTrue(hasProperties));
90+
}
91+
92+
protected readComponentTemplateMetadata(dec: ts.Decorator, external: MetadataUrls): Maybe<TemplateMetadata> {
93+
// Resolve Inline template
94+
return getTemplate(dec)
95+
.fmap(inlineTemplate => ({
96+
template: normalizeTransformed(Config.transformTemplate(inlineTemplate.text, null, dec)),
97+
url: null,
98+
node: inlineTemplate,
99+
})
100+
).catch(() => // If there's no valid inline template, we resolve external template
101+
Maybe.lift(external.templateUrl)
102+
.bind(url =>
103+
this._resolve(url).fmap(template => ({
104+
template: normalizeTransformed(Config.transformTemplate(template, url, dec)),
105+
url,
106+
node: null
107+
}))
108+
)
109+
);
110+
}
111+
112+
protected readComponentStylesMetadata(dec: ts.Decorator, external: MetadataUrls): Maybe<StylesMetadata> {
113+
return getInlineStyle(dec).fmap(inlineStyles =>
114+
// Resolve Inline styles
115+
inlineStyles.elements.map((inlineStyle: ts.Expression) => {
116+
if (isSimpleTemplateString(inlineStyle)) {
117+
return {
118+
style: normalizeTransformed(Config.transformStyle(inlineStyle.text, null, dec)),
119+
url: null,
120+
node: inlineStyle as ts.Node,
121+
};
96122
}
123+
}).filter(v => !!v)
124+
).catch(() => // If there's no valid inline styles, we resolve external styles
125+
Maybe.lift(external.styleUrls)
126+
.fmap(urls => urls.map(url => // Resolve each style URL and transform to metadata
127+
this._resolve(url).fmap(style => ({
128+
style: normalizeTransformed(Config.transformStyle(style, url, dec)),
129+
url,
130+
node: null,
131+
}))
132+
))
133+
// merge Maybe<StyleMetadata>[] to Maybe<StyleMetadata[]>
134+
.bind(url_Ms => listToMaybe<StyleMetadata>(url_Ms))
135+
);
136+
}
137+
138+
private _resolve(url: string): Maybe<string> {
139+
try {
140+
return Maybe.lift(this._fileResolver.resolve(url));
141+
} catch (e) {
142+
logger.info('Cannot read file' + url);
143+
return Maybe.nothing;
97144
}
98-
99-
readComponentStylesMetadata(dec: ts.Decorator, external: MetadataUrls) {
100-
let styles: any[];
101-
const inlineStyles_M = getInlineStyle(dec)
102-
.fmap(inlineStyles => {
103-
return inlineStyles.elements.map((inlineStyle: ts.Expression) => {
104-
if (isSimpleTemplateString(inlineStyle)) {
105-
return {
106-
style: normalizeTransformed(Config.transformStyle(inlineStyle.text, null, dec)),
107-
url: null,
108-
node: inlineStyle,
109-
};
110-
}
111-
}).filter(v => !!v);
112-
});
113-
114-
if (inlineStyles_M.isSomething) {
115-
return inlineStyles_M.unwrap();
116-
} else if (external.styleUrls) {
117-
// TODO: Refactoring this requires adding seem to fileResolver
118-
try {
119-
styles = <any>external.styleUrls.map((url: string) => {
120-
const style = this._fileResolver.resolve(url);
121-
const transformed = normalizeTransformed(Config.transformStyle(style, url, dec));
122-
return {
123-
style: transformed, url,
124-
node: null
125-
};
126-
});
127-
} catch (e) {
128-
logger.info('Unable to read external style. ' + e.toString());
129-
}
130-
}
131-
return styles;
132-
}
133-
134-
readComponentMetadata(d: ts.ClassDeclaration, dec: ts.Decorator) {
135-
const expr = this.getDecoratorArgument(dec);
136-
const directiveMetadata = this.readDirectiveMetadata(d, dec);
137-
138-
const external_M = expr.fmap(() => this._urlResolver.resolve(dec));
139-
140-
const template_M = external_M.fmap(
141-
(external) => this.readComponentTemplateMetadata(dec, external));
142-
const style_M = external_M.fmap(
143-
(external) => this.readComponentStylesMetadata(dec, external));
144-
145-
return Object.assign(new ComponentMetadata(), directiveMetadata, {
146-
template: template_M.unwrap(),
147-
styles: style_M.unwrap(),
148-
});
149-
}
150-
151-
protected getDecoratorArgument(decorator: ts.Decorator): Maybe<ts.ObjectLiteralExpression> {
152-
return decoratorArgument(decorator)
153-
.bind(ifTrue(hasProperties));
154-
}
145+
}
155146
}

0 commit comments

Comments
 (0)