Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print compiler reports in console at runtime. #15

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server"
"start": "webpack-dev-server",
"build": "webpack --mode development"
},
"dependencies": {
"react": "^16.13.1",
Expand Down
18 changes: 16 additions & 2 deletions example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ import stylemug from 'stylemug';
import { globalStyles } from './globals';

const styles = stylemug.create({
foo: 'bar',
title: {
fontSize: '31px',
fontFamily: 'courier',
color: '#444',
color: 'green',
},
titleRed: {
color: 'red',
'&:hoverr': {
color: 'red',
},
},
});

const secondaryStyles = stylemug.create({
color: {
color: '#444',
},
});

Expand All @@ -22,7 +32,11 @@ export default function App() {

return (
<div className={styles(globalStyles.container)}>
<h1 className={styles('title', show && 'titleRed')}>Hello World</h1>
<h1
className={styles('title', secondaryStyles.color, show && 'titleRed')}
>
Hello World
</h1>
<button onClick={onClick}>Click</button>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`babel plugin - reports should replace create argument 1`] = `
"\\"use strict\\";

var _stylemug = _interopRequireDefault(require(\\"stylemug\\"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \\"default\\": obj }; }

var styles = _stylemug[\\"default\\"].create({}, {
sourceLinesRange: \\"In lines 4 to 4\\",
messages: [\\"mockError1\\", \\"mockError2\\"]
});"
`;

exports[`babel plugin should error when failed to resolve 1`] = `
"\\"use strict\\";

Expand All @@ -13,7 +26,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope

var styles = _stylemug[\\"default\\"].create(_defineProperty({}, _mock.selector, {
color: 'red'
}), \\"Failed to evaluate the following stylesheet: \\\\n\\\\nstylemug.create({\\\\n [selector]: {\\\\n color: 'red'\\\\n }\\\\n})\\\\n\\\\nMake sure your stylesheet is statically defined.\\");"
}), {
sourceLinesRange: \\"In lines 5 to 9\\",
messages: [\\"Failed to evaluate the following stylesheet: \\\\n\\\\nstylemug.create({\\\\n [selector]: {\\\\n color: 'red'\\\\n }\\\\n})\\\\n\\\\nMake sure your stylesheet is statically defined.\\"]
});"
`;

exports[`babel plugin should replace create argument 1`] = `
Expand Down
43 changes: 36 additions & 7 deletions packages/babel-stylemug-plugin/src/__test__/babel.test.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import { transform } from '@babel/core';
import { compileSchema } from 'stylemug-compiler';
import { babelPlugin as plugin } from '../babel';

jest.mock('stylemug-compiler', () => ({
compileSchema: () => ({
className: {
hash: {
keyId: 'id',
},
},
}),
compileSchema: jest.fn(),
}));

describe('babel plugin', () => {
beforeEach(() => {
compileSchema.mockImplementationOnce(() => ({
result: {
className: {
hash: {
keyId: 'id',
},
},
},
reports: [],
}));
});

it('should replace create argument', () => {
const example = `
import stylemug from 'stylemug';
Expand Down Expand Up @@ -73,3 +81,24 @@ describe('babel plugin', () => {
expect(code).toMatchSnapshot();
});
});

describe('babel plugin - reports', () => {
it('should replace create argument', () => {
compileSchema.mockImplementationOnce(() => ({
result: {},
reports: [{ message: 'mockError1' }, { message: 'mockError2' }],
}));

const example = `
import stylemug from 'stylemug';

const styles = stylemug.create({});
`;

const { code } = transform(example, {
plugins: [plugin],
});

expect(code).toMatchSnapshot();
});
});
52 changes: 42 additions & 10 deletions packages/babel-stylemug-plugin/src/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,39 @@ import { compileSchema } from 'stylemug-compiler';
export function babelPlugin(babel) {
const t = babel.types;

function defineError(path, msg) {
function wrapReports(path, reports) {
if (!Array.isArray(reports)) {
reports = [reports];
}
if (!reports.length) {
return;
}

const node = t.cloneDeep(path.node);
node.arguments[1] = t.stringLiteral(msg);
const objectChilds = [
t.objectProperty(
t.identifier('sourceLinesRange'),
t.stringLiteral(
'In lines ' + node.loc.start.line + ' to ' + node.loc.end.line
)
),
t.objectProperty(
t.identifier('messages'),
t.arrayExpression(
reports.map((report) => t.stringLiteral(report.message))
)
),
];
if (path.hub.file.opts.filename) {
objectChilds.push(
t.objectProperty(
t.identifier('fileName'),
t.stringLiteral(path.hub.file.opts.filename || 'unknown')
)
);
}

node.arguments[1] = t.objectExpression(objectChilds);
path.replaceWith(node);
}

Expand All @@ -34,22 +64,24 @@ export function babelPlugin(babel) {
references.forEach((reference) => {
const local = reference.parentPath.parentPath;

let sheet = evaluateSimple(local.get('arguments')[0]);
const sheet = evaluateSimple(local.get('arguments')[0]);
if (!sheet.confident) {
defineError(
local,
'Failed to evaluate the following stylesheet: \n\n' +
wrapReports(local, {
message:
'Failed to evaluate the following stylesheet: \n\n' +
local.toString() +
'\n\n' +
'Make sure your stylesheet is statically defined.'
);
'Make sure your stylesheet is statically defined.',
});
return;
}
sheet = compileSchema(sheet.value);

const { result, reports } = compileSchema(sheet.value);
wrapReports(local, reports);

const nextLocal = t.cloneDeep(local.node);
nextLocal.arguments[0] = t.objectExpression(
Object.entries(sheet).map(([name, rules]) => {
Object.entries(result).map(([name, rules]) => {
return t.objectProperty(
t.identifier(name),
t.objectExpression(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`compile should assert an invalid rule value 1`] = `
Array [
Object {
"message": "Invalid type for color",
},
]
`;

exports[`compile should assert an invalid sheet 1`] = `
Object {
"default": Object {
"b765dfa68": Object {
"children": "",
"key": "backgroundColor",
"keyId": "bb7c5a6d0",
"media": undefined,
"value": "yellow",
},
"cb34cd11f": Object {
"children": "",
"key": "color",
"keyId": "c3d7e6258",
"media": undefined,
"value": "red",
},
},
}
`;

exports[`compile should assert an invalid sheet 2`] = `
Array [
Object {
"message": "Classname with key foo is not an object",
},
]
`;

exports[`compile should assert invalid pseudo classes 1`] = `
Array [
Object {
"message": "&:iAmAnInvalidPseudoClass is an invalid CSS pseudo class / element",
},
Object {
"message": "Invalid type for color",
},
]
`;

exports[`compile should report multiple errors 1`] = `
Array [
Object {
"message": "Classname with key foo is not an object",
},
Object {
"message": "&:iAmAnInvalidPseudoClass is an invalid CSS pseudo class / element",
},
Object {
"message": "Invalid type for color",
},
]
`;
52 changes: 52 additions & 0 deletions packages/stylemug-compiler/src/__test__/compile-context.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { compileSchema } from '../compile';

describe('compile', () => {
it('should assert an invalid sheet', () => {
const { result, reports } = compileSchema({
default: {
color: 'red',
backgroundColor: 'yellow',
},
// The rule below fails.
foo: 'bar',
});

expect(result).toMatchSnapshot();
expect(reports).toMatchSnapshot();
});

it('should assert an invalid rule value', () => {
const { reports } = compileSchema({
default: {
color: true,
},
});

expect(reports).toMatchSnapshot();
});

it('should assert invalid pseudo classes', () => {
const { reports } = compileSchema({
default: {
'&:iAmAnInvalidPseudoClass': {
color: true,
},
},
});

expect(reports).toMatchSnapshot();
});

it('should report multiple errors', () => {
const { reports } = compileSchema({
foo: 'bar',
default: {
'&:iAmAnInvalidPseudoClass': {
color: true,
},
},
});

expect(reports).toMatchSnapshot();
});
});
21 changes: 10 additions & 11 deletions packages/stylemug-compiler/src/__test__/compile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { compileSchema, compileSelectors } from '../compile';

describe('compile', () => {
it('should compile schema', () => {
const result = compileSchema({
const { result } = compileSchema({
default: {
color: 'red',
backgroundColor: 'yellow',
Expand All @@ -18,16 +18,8 @@ describe('compile', () => {
expect(result).toMatchSnapshot();
});

it('should compile selectors with number as value', () => {
const result = compileSelectors({
fontSize: 12,
});

expect(result).toMatchSnapshot();
});

it('should compile nested selectors', () => {
const result = compileSchema({
const { result } = compileSchema({
default: {
color: 'red',

Expand All @@ -41,7 +33,7 @@ describe('compile', () => {
});

it('should compile nested media query', () => {
const result = compileSchema({
const { result } = compileSchema({
default: {
color: 'red',

Expand All @@ -53,4 +45,11 @@ describe('compile', () => {

expect(result).toMatchSnapshot();
});

it('should compile selectors with number as value', () => {
const result = compileSelectors({
fontSize: 12,
});
expect(result).toMatchSnapshot();
});
});
Loading