Skip to content

Commit

Permalink
fix(compiler-cli): enableResourceInlining handles both styles and sty…
Browse files Browse the repository at this point in the history
…leUrls

When both are present, the inlined styles are appended to the end of the styles
  • Loading branch information
alexeagle committed Mar 9, 2018
1 parent 8594afe commit 4d4e280
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 47 deletions.
107 changes: 61 additions & 46 deletions packages/compiler-cli/src/transformers/inline_resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,20 @@ export class InlineResourcesMetadataTransformer implements MetadataTransformer {
arg['template'] = loader.get(arg['templateUrl']);
delete arg.templateUrl;
}
if (arg['styleUrls']) {
const styleUrls = arg['styleUrls'];
if (Array.isArray(styleUrls)) {
arg['styles'] = styleUrls.map(styleUrl => loader.get(styleUrl));
delete arg.styleUrls;

const styles = arg['styles'];
const styleUrls = arg['styleUrls'];

if (styleUrls) {
if (!Array.isArray(styleUrls)) throw new Error('styleUrls should be an array');
const inlinedStyles = styleUrls.map(styleUrl => loader.get(styleUrl));
if (styles) {
if (!Array.isArray(styles)) throw new Error('styles should be an array');
styles.push(...inlinedStyles);
} else {
arg['styles'] = inlinedStyles;
}
delete arg.styleUrls;
}

return arg;
Expand Down Expand Up @@ -262,49 +270,56 @@ function updateComponentProperties(
// argument
return args;
}
const newArgument = ts.updateObjectLiteral(
componentArg, ts.visitNodes(componentArg.properties, (node: ts.ObjectLiteralElementLike) => {
if (!ts.isPropertyAssignment(node)) {
// Error: unsupported
return node;
}

if (ts.isComputedPropertyName(node.name)) {
// computed names are not supported
return node;
const newProperties: ts.ObjectLiteralElementLike[] = [];
const newStyleExprs: ts.Expression[] = [];
componentArg.properties.forEach(prop => {
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) {
newProperties.push(prop);
return;
}

switch (prop.name.text) {
case 'styles':
if (!ts.isArrayLiteralExpression(prop.initializer)) {
throw new Error('styles takes an array argument');
}
newStyleExprs.push(...prop.initializer.elements);
break;

const name = node.name.text;
switch (name) {
case 'styleUrls':
if (!ts.isArrayLiteralExpression(node.initializer)) {
// Error: unsupported
return node;
}
const styleUrls = node.initializer.elements;

return ts.updatePropertyAssignment(
node, ts.createIdentifier('styles'),
ts.createArrayLiteral(ts.visitNodes(styleUrls, (expr: ts.Expression) => {
if (ts.isStringLiteral(expr)) {
const styles = loader.get(expr.text);
return ts.createLiteral(styles);
}
return expr;
})));


case 'templateUrl':
if (ts.isStringLiteral(node.initializer)) {
const template = loader.get(node.initializer.text);
return ts.updatePropertyAssignment(
node, ts.createIdentifier('template'), ts.createLiteral(template));
}
return node;

default:
return node;
case 'styleUrls':
if (!ts.isArrayLiteralExpression(prop.initializer)) {
throw new Error('styles takes an array argument');
}
newStyleExprs.push(...prop.initializer.elements.map((expr: ts.Expression) => {
if (!ts.isStringLiteral(expr)) {
throw new Error(
'Can only accept string literal arguments to styleUrls. ' + PRECONDITIONS_TEXT);
}
const styles = loader.get(expr.text);
return ts.createLiteral(styles);
}));
break;

case 'templateUrl':
if (!ts.isStringLiteral(prop.initializer)) {
throw new Error(
'Can only accept string literal arguments to templateUrl. ' + PRECONDITIONS_TEXT);
}
}));
return ts.createNodeArray<ts.Expression>([newArgument]);
const template = loader.get(prop.initializer.text);
newProperties.push(ts.updatePropertyAssignment(
prop, ts.createIdentifier('template'), ts.createLiteral(template)));
break;

default:
newProperties.push(prop);
}
});

// Add the non-inline styles
const newStyles = ts.createPropertyAssignment(
ts.createIdentifier('styles'), ts.createArrayLiteral(newStyleExprs));
newProperties.push(newStyles);

return ts.createNodeArray([ts.updateObjectLiteral(componentArg, newProperties)]);
}
13 changes: 12 additions & 1 deletion packages/compiler-cli/test/transformers/inline_resources_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ describe('inline resources transformer', () => {
expect(actual).not.toContain('styleUrls:');
expect(actual).toContain('styles: [".some_style {}", ".some_other_style {}"]');
});
it('should preserve existing styles', () => {
const actual = convert(`import {Component} from '@angular/core';
@Component({
styles: ['h1 { color: blue }'],
styleUrls: ['./thing1.css'],
})
export class Foo {}`);
expect(actual).not.toContain('styleUrls:');
expect(actual).toContain(`styles: ['h1 { color: blue }', ".some_style {}"]`);
});
it('should handle empty styleUrls', () => {
const actual = convert(`import {Component} from '@angular/core';
@Component({styleUrls: []}) export class Foo {}`);
Expand Down Expand Up @@ -115,6 +125,7 @@ describe('metadata transformer', () => {
@Component({
templateUrl: './thing.html',
styleUrls: ['./thing1.css', './thing2.css'],
styles: ['h1 { color: red }'],
})
export class Foo {}
`;
Expand All @@ -135,7 +146,7 @@ describe('metadata transformer', () => {
expect(JSON.stringify(classData)).toContain('"template":"Some template"');
expect(JSON.stringify(classData)).not.toContain('styleUrls');
expect(JSON.stringify(classData))
.toContain('"styles":[".some_style {}",".some_other_style {}"]');
.toContain('"styles":["h1 { color: red }",".some_style {}",".some_other_style {}"]');
}
}
});
Expand Down

0 comments on commit 4d4e280

Please sign in to comment.