Skip to content

Commit

Permalink
feat: transform 'styles' only in decorator
Browse files Browse the repository at this point in the history
Until now we transformed 'templateUrl', 'styleUrls' and 'styles'
everywhere they were assigned.

The new implementation of the AstTransformer splits it in two:
* InlineFilesTransformer, which inlines `templateUrl` and removes
  `styleUrls` files
* StripStylesTransformer, which removes the `styles` property, but only
  inside the `@Component` decorator
  • Loading branch information
wtho committed Jun 10, 2019
1 parent 1079528 commit 6272b7f
Show file tree
Hide file tree
Showing 9 changed files with 445 additions and 112 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
node_modules
InlineHtmlStripStylesTransformer.js
InlineFilesTransformer.js
StripStylesTransformer.js
TransformUtils.js
*.log
.idea
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*
* Code is inspired by
* https://github.com/kulshekhar/ts-jest/blob/25e1c63dd3797793b0f46fa52fdee580b46f66ae/src/transformers/hoist-jest.spec.ts
*
*
*/

import * as tsc from 'typescript'
import * as transformer from '../InlineHtmlStripStylesTransformer'
import * as tsc from 'typescript';
import * as transformer from '../InlineFilesTransformer';

const CODE_WITH_TEMPLATE_URL = `
import { Component } from '@angular/core';
Expand All @@ -15,7 +15,7 @@ const CODE_WITH_TEMPLATE_URL = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_NON_RELATIVE_TEMPLATE_URL = `
import { Component } from '@angular/core';
Expand All @@ -25,7 +25,7 @@ const CODE_WITH_NON_RELATIVE_TEMPLATE_URL = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_STYLE_URLS = `
import { Component } from '@angular/core';
Expand All @@ -38,7 +38,7 @@ const CODE_WITH_STYLE_URLS = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_STYLES = `
import { Component } from '@angular/core';
Expand All @@ -51,7 +51,7 @@ const CODE_WITH_STYLES = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_ALL_DECORATOR_PROPERTIES = `
import { Component } from '@angular/core';
Expand All @@ -76,7 +76,7 @@ const CODE_WITH_ALL_DECORATOR_PROPERTIES = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_CUSTOM_DECORATOR = `
import { Component as CustomDecoratorName } from '@angular/core';
Expand All @@ -86,7 +86,7 @@ const CODE_WITH_CUSTOM_DECORATOR = `
})
export class AngularComponent {
}
`
`;

const CODE_TEST_WITH_TEMPLATE_URL_OVERRIDE = `
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
Expand Down Expand Up @@ -117,62 +117,80 @@ describe('AComponent', () => {
expect(fixture).toMatchSnapshot();
});
});
`


`;

const CODE_WITH_ASSIGNMENTS_OUTSIDE_DECORATOR = `
const assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
const assignmentsToBeTransformed = {
styleUrls: ['./some-styles.css'],
templateUrl: './some-styles.css'
};
`;

const createFactory = () => {
return transformer.factory({ compilerModule: tsc } as any)
}
const transpile = (source: string) => tsc.transpileModule(source, { transformers: { before: [createFactory()] } })
return transformer.factory({ compilerModule: tsc } as any);
};
const transpile = (source: string) =>
tsc.transpileModule(source, { transformers: { before: [createFactory()] } });


describe('inlining template and stripping styles', () => {
it('should have correct signature', () => {
expect(transformer.name).toBe('angular-component-inline-template-strip-styles')
expect(typeof transformer.version).toBe('number')
expect(transformer.version).toBeGreaterThan(0)
expect(typeof transformer.factory).toBe('function')
})
expect(transformer.name).toBe('angular-component-inline-files');
expect(typeof transformer.version).toBe('number');
expect(transformer.version).toBeGreaterThan(0);
expect(typeof transformer.factory).toBe('function');
});

it('should strip styleUrl assignment', () => {
const out = transpile(CODE_WITH_STYLE_URLS)
const out = transpile(CODE_WITH_STYLE_URLS);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should strip styles assignment', () => {
const out = transpile(CODE_WITH_STYLES)
const out = transpile(CODE_WITH_STYLES);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should inline templateUrl assignment', () => {
const out = transpile(CODE_WITH_TEMPLATE_URL)
const out = transpile(CODE_WITH_TEMPLATE_URL);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should inline non-relative templateUrl assignment and make it relative', () => {
const out = transpile(CODE_WITH_NON_RELATIVE_TEMPLATE_URL)
const out = transpile(CODE_WITH_NON_RELATIVE_TEMPLATE_URL);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should handle all transformable decorator assignments', () => {
const out = transpile(CODE_WITH_ALL_DECORATOR_PROPERTIES)
const out = transpile(CODE_WITH_ALL_DECORATOR_PROPERTIES);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should handle all decorator assignments in differently named decorators', () => {
const out = transpile(CODE_WITH_CUSTOM_DECORATOR)
const out = transpile(CODE_WITH_CUSTOM_DECORATOR);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should handle templateUrl in test file outside decorator', () => {
const out = transpile(CODE_TEST_WITH_TEMPLATE_URL_OVERRIDE)
const out = transpile(CODE_TEST_WITH_TEMPLATE_URL_OVERRIDE);

expect(out.outputText).toMatchSnapshot()
})
})
expect(out.outputText).toMatchSnapshot();
});

it('should not transform styles outside decorator', () => {
const out = transpile(CODE_WITH_ASSIGNMENTS_OUTSIDE_DECORATOR);

expect(out.outputText).toMatchSnapshot();
});
});
68 changes: 68 additions & 0 deletions __tests__/StripStylesTransformer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Code is inspired by
* https://github.com/kulshekhar/ts-jest/blob/25e1c63dd3797793b0f46fa52fdee580b46f66ae/src/transformers/hoist-jest.spec.ts
*
*/

import * as tsc from 'typescript';
import * as transformer from '../StripStylesTransformer';

const CODE_WITH_STYLES_AND_OTHER_ASSIGNMENTS = `
import { Component } from '@angular/core';
@SomeDecorator({
value: 'test',
styles: [
':host { background-color: red }'
],
})
@Component({
templateUrl: './page.html',
styleUrls: [
'./fancy-styles.css',
'./basic-styles.scss'
],
styles: [
'body { display: none }',
'html { background-color: red }'
],
unaffectedProperty: 'whatever'
})
export class AngularComponent {
}
`;

const CODE_WITH_ASSIGNMENT_OUTSIDE_DECORATOR = `
const assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
`;

const createFactory = () => {
return transformer.factory({ compilerModule: tsc } as any);
};
const transpile = (source: string) =>
tsc.transpileModule(source, { transformers: { before: [createFactory()] } });

describe('inlining template and stripping styles', () => {
it('should have correct signature', () => {
expect(transformer.name).toBe('angular-component-strip-styles');
expect(typeof transformer.version).toBe('number');
expect(transformer.version).toBeGreaterThan(0);
expect(typeof transformer.factory).toBe('function');
});

it('should strip styleUrl assignment', () => {
const out = transpile(CODE_WITH_STYLES_AND_OTHER_ASSIGNMENTS);

expect(out.outputText).toMatchSnapshot();
});

it('should not transform styles outside decorator', () => {
const out = transpile(CODE_WITH_ASSIGNMENT_OUTSIDE_DECORATOR);

expect(out.outputText).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ var AngularComponent = /** @class */ (function () {
core_1.Component({
template: require('./page.html'),
styleUrls: [],
styles: [],
styles: [
'body: { display: none }',
'html: { background-color: red }'
],
unaffectedProperty: 'whatever'
}),
SomeOtherDecorator({
Expand Down Expand Up @@ -133,6 +136,19 @@ exports.AngularComponent = AngularComponent;
"
`;

exports[`inlining template and stripping styles should not transform styles outside decorator 1`] = `
"var assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
var assignmentsToBeTransformed = {
styleUrls: [],
template: require('./some-styles.css')
};
"
`;

exports[`inlining template and stripping styles should strip styleUrl assignment 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
Expand Down Expand Up @@ -172,7 +188,10 @@ var AngularComponent = /** @class */ (function () {
}
AngularComponent = __decorate([
core_1.Component({
styles: []
styles: [
'body: { display: none }',
'html: { background-color: red }'
]
})
], AngularComponent);
return AngularComponent;
Expand Down
46 changes: 46 additions & 0 deletions __tests__/__snapshots__/StripStylesTransformer.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`inlining template and stripping styles should not transform styles outside decorator 1`] = `
"var assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
"
`;

exports[`inlining template and stripping styles should strip styleUrl assignment 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === \\"object\\" && typeof Reflect.decorate === \\"function\\") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, \\"__esModule\\", { value: true });
var core_1 = require(\\"@angular/core\\");
var AngularComponent = /** @class */ (function () {
function AngularComponent() {
}
AngularComponent = __decorate([
SomeDecorator({
value: 'test',
styles: [
':host { background-color: red }'
],
}),
core_1.Component({
templateUrl: './page.html',
styleUrls: [
'./fancy-styles.css',
'./basic-styles.scss'
],
styles: [],
unaffectedProperty: 'whatever'
})
], AngularComponent);
return AngularComponent;
}());
exports.AngularComponent = AngularComponent;
"
`;
5 changes: 4 additions & 1 deletion jest-preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ module.exports = {
'ts-jest': {
tsConfig: '<rootDir>/src/tsconfig.spec.json',
stringifyContentPathRegex: '\\.html$',
astTransformers: [require.resolve('./InlineHtmlStripStylesTransformer')],
astTransformers: [
require.resolve('./InlineFilesTransformer'),
require.resolve('./StripStylesTransformer'),
],
},
},
transform: {
Expand Down
Loading

0 comments on commit 6272b7f

Please sign in to comment.