Skip to content

Commit

Permalink
Enhancement/issue 426 restore userland postcss (#453)
Browse files Browse the repository at this point in the history
* user postcss plugins for production

* userland postcss from css transform

* restore nested styles for components

* renable and update PostCSS test case

* reference projectDirectory context in rollup

* update build docs for PostCSS configuration

* fix link
  • Loading branch information
thescientist13 committed Apr 3, 2021
1 parent 3ff4e52 commit bb21966
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 120 deletions.
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
},
"devDependencies": {
"@mapbox/rehype-prism": "^0.5.0",
"postcss-nested": "^4.1.2",
"rehype-autolink-headings": "^4.0.0",
"rehype-slug": "^3.0.0"
}
Expand Down
20 changes: 16 additions & 4 deletions packages/cli/src/config/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function greenwoodWorkspaceResolver (compilation) {

// https://github.com/rollup/rollup/issues/2873
function greenwoodHtmlPlugin(compilation) {
const { userWorkspace, outputDir } = compilation.context;
const { projectDirectory, userWorkspace, outputDir } = compilation.context;

return {
name: 'greenwood-html-plugin',
Expand Down Expand Up @@ -117,15 +117,27 @@ function greenwoodHtmlPlugin(compilation) {
}

// this is a giant work around because PostCSS and some plugins can only be run async
// and so have to use with awit but _outside_ sync code, like parser / rollup
// and so have to use with await but _outside_ sync code, like parser / rollup
// https://github.com/cssnano/cssnano/issues/68
// https://github.com/postcss/postcss/issues/595
// TODO consider similar approach for emitting chunks?
return Promise.all(Object.keys(mappedStyles).map(async (assetKey) => {
const asset = mappedStyles[assetKey];
const filePath = path.join(userWorkspace, asset.name);

const result = await postcss(postcssConfig.plugins)
// TODO we already process the user's CSS as part of serve lifecycle (dev / build commands)
// if we pull from .greenwood/ then maybe we could avoid re-postcss step here?
const userPostcssConfig = fs.existsSync(`${projectDirectory}/postcss.config.js`)
? require(`${projectDirectory}/postcss.config`)
: {};
const userPostcssPlugins = userPostcssConfig.plugins && userPostcssConfig.plugins.length > 0
? userPostcssConfig.plugins
: [];
const allPostcssPlugins = [
...userPostcssPlugins,
...postcssConfig.plugins
];

const result = await postcss(allPostcssPlugins)
.use(postcssImport())
.process(asset.source, { from: filePath });

Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/lifecycles/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = initContexts = async({ config }) => {
return new Promise(async (resolve, reject) => {

try {
const projectDirectory = process.cwd();
const userWorkspace = path.join(config.workspace);
const pagesDir = path.join(userWorkspace, 'pages/');
const userTemplatesDir = path.join(userWorkspace, 'templates/');
Expand All @@ -19,7 +20,8 @@ module.exports = initContexts = async({ config }) => {
userWorkspace,
pagesDir,
userTemplatesDir,
scratchDir
scratchDir,
projectDirectory
};

if (!fs.existsSync(scratchDir)) {
Expand Down
18 changes: 16 additions & 2 deletions packages/cli/src/transforms/transform.css.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const fs = require('fs');
const path = require('path');
const { promises: fsp } = require('fs');
const postcss = require('postcss');
const TransformInterface = require('./transform.interface');

class CSSTransform extends TransformInterface {
Expand All @@ -18,9 +19,22 @@ class CSSTransform extends TransformInterface {
? path.join(process.cwd(), url)
: path.join(this.workspace, url);

const css = await fsp.readFile(cssPath, 'utf-8');
let css = await fs.promises.readFile(cssPath, 'utf-8');
let body = '', contentType = '';

// TODO try and use context.projectDirectory
if (fs.existsSync(path.join(process.cwd(), 'postcss.config.js'))) {
const userPostcssConfig = require(`${process.cwd()}/postcss.config`);
const userPostcssPlugins = userPostcssConfig.plugins || [];

if (userPostcssPlugins.length > 0) {
const result = await postcss(userPostcssPlugins)
.process(css, { from: cssPath });

css = result.css;
}
}

// <style> tag used
if (destHeader === 'style') {
contentType = 'text/css';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/*
* Use Case
* Run Greenwood with a custom postcss config
* Run Greenwood with a custom PostCSS config
*
* User Result
* Should generate a bare bones Greenwood build with a hello page containing a component with a
* @custom-media query
* Should generate a bare bones Greenwood build with the user's CSS file correctly un-nested and minified
*
* User Command
* greenwood build
Expand All @@ -13,16 +12,18 @@
* Greenwood default
* src/
* pages/
* hello.md
* index.md
* index.html
* styles/
* main.css
*/
const { JSDOM } = require('jsdom');
const fs = require('fs');
const glob = require('glob-promise');
const path = require('path');
const expect = require('chai').expect;
const runSmokeTest = require('../../../../../test/smoke-test');
const TestBed = require('../../../../../test/test-bed');

xdescribe('Build Greenwood With: ', function() {
describe('Build Greenwood With: ', function() {
const LABEL = 'Custom PostCSS configuration';
let setup;

Expand All @@ -37,27 +38,17 @@ xdescribe('Build Greenwood With: ', function() {
await setup.runGreenwoodCommand('build');
});

runSmokeTest(['public', 'index', 'not-found', 'hello'], LABEL);
// TODO runSmokeTest(['public', 'index', 'not-found'], LABEL);
runSmokeTest(['public', 'index'], LABEL);

describe('Hello page with working @custom-media queries', function() {
let dom;
describe('Page referencing external nested CSS file', function() {
it('should output correctly processed nested CSS as non nested', function() {
const expectedCss = 'body{color:red}body h1{color:#00f}';
const cssFiles = glob.sync(path.join(this.context.publicDir, 'styles', '*.css'));
const css = fs.readFileSync(cssFiles[0], 'utf-8');

beforeEach(async function() {
dom = await JSDOM.fromFile(path.resolve(this.context.publicDir, './hello/index.html'));
});

it('should resolve the correct @custom-media queries for eve-container', function() {
// check @media (--screen-xs) resolves to @media (max-width:576px) via postcss preset-env: stage 1
const expectedStyle = 'eve-container .container.eve-container,eve-container ' +
'.container-fluid.eve-container {\n margin-right:auto;margin-left:auto;padding-left:15px;' +
'padding-right:15px\n}\n\n@media (max-width:576px) {\neve-container .container.eve-container ' +
'{\n width:calc(100% - 30px)\n}\n\n}\n\n@media (min-width:576px) {\neve-container ' +
'.container.eve-container {\n width:540px\n}\n\n}\n\n@media (min-width:768px) {\neve-container ' +
'.container.eve-container {\n width:720px\n}\n\n}\n\n@media (min-width:992px) {\neve-container ' +
'.container.eve-container {\n width:960px\n}\n\n}\n\n@media (min-width:1200px) {\neve-container ' +
'.container.eve-container {\n width:1140px\n}\n\n}';
const containerStyle = dom.window.document.head.querySelector('style[scope="eve-container"]');
expect(containerStyle.innerHTML).to.equal(expectedStyle);
expect(cssFiles.length).to.equal(1);
expect(css).to.equal(expectedCss);
});
});
});
Expand Down
10 changes: 3 additions & 7 deletions packages/cli/test/cases/build.config.postcss/postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
module.exports = {
plugins: {
'postcss-preset-env': {
stage: 1
},
'postcss-nested': {},
'cssnano': {}
}
plugins: [
require('postcss-nested')
]
};
11 changes: 0 additions & 11 deletions packages/cli/test/cases/build.config.postcss/src/pages/hello.md

This file was deleted.

12 changes: 12 additions & 0 deletions packages/cli/test/cases/build.config.postcss/src/pages/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">

<head>
<link rel="stylesheet" href="/styles/main.css"></link>
</head>

<body>
<h1>Hello World!</h1>
</body>

</html>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
body {
color: red;

& h1 {
color: blue;
}

}
10 changes: 3 additions & 7 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
module.exports = {
// plugins: {
// 'postcss-preset-env': {
// stage: 1
// },
// 'postcss-nested': {},
// 'cssnano': {}
// }
plugins: [
require('postcss-nested')
]
};
2 changes: 1 addition & 1 deletion www/components/row/row.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
@media (max-width: 1024px) {
flex-direction: column;
}
}
}
2 changes: 1 addition & 1 deletion www/components/social-icons/social-icons.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
@media (max-width: 768px) {
flex-direction: row;
}
}
}
1 change: 1 addition & 0 deletions www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"devDependencies": {
"@mapbox/rehype-prism": "^0.5.0",
"postcss-nested": "^4.1.2",
"rehype-autolink-headings": "^4.0.0",
"rehype-slug": "^3.0.0",
"remark-github": "^10.0.1"
Expand Down
62 changes: 55 additions & 7 deletions www/pages/docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,61 @@ index: 4
linkheadings: 3
---

# Build Configurations
> [_**Coming Soon!**_](https://github.com/ProjectEvergreen/greenwood/issues/426)
## Build Configurations
> [_**More coming Soon!**_](https://github.com/ProjectEvergreen/greenwood/issues/426)
**Greenwood** offers the ability to extend some of the internal tooling used to better customize the project for those with more advanced use cases than those offered by Greenwood's default. Greenwood is farily unopinionated in its defaults and aims to provide support for modern web standards that are >= Stage 3 (where applicable).

> _For markdown specific options, please see our docs section on [markdown](/docs/markdown/)._
### PostCSS

To provide addition configurations and optimizations around CSS, user's can add a _postcss.config.js_ file within a project's root directory to take advantage of [**PostCSS**](https://postcss.org/).

For example, if you wanted to write CSS with nested selectors, you would want do the following:

1. Install the relevant PostCSS plugin
```shell
$ npm install postcss-nested --save-dev
```
1. Create a _postcss.config.js_ file and `require` your plugin
```js
module.exports = {
plugins: [
require('postcss-nested')
]
};
```
1. Now you can write nested CSS!
```css
:host {
& .card {
padding: 2.5rem;
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: initial;
text-align: center;
& .body {
padding:10px;
}
@media(max-width:768px) {
padding:0;
}
}
}
```

> _For reference, [this is the default postcss.config.js](https://github.com/ProjectEvergreen/greenwood/blob/master/packages/cli/src/config/postcss.config.js) being provided by Greenwood._

<!--
> Note: [.browserslistrc](#browserslist) is used by postcss and is also needed to be overwritten. You can override that in that same directory or you may also configure postcss-preset-env to use default `.browserslistrc` path via environement variable to: `./node_modules/@greenwood/cli/src/config/.browserslistrc`. See [postcss-preset-env docs](https://www.npmjs.com/package/postcss-preset-env#browsers) for further information. [Ejecting configuration](#eject-configuration) is one way in which you can easily override both with no extra configuraiton.
-->

<!--
A number of [core build configuration files](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/cli/src/config) can be overridden by creating each file within the root path of your project. You can also automate this task in a single command [see eject configurations](#eject-configurations).
Expand Down Expand Up @@ -36,11 +89,6 @@ By default, [this is the postcss.config.js](https://github.com/ProjectEvergreen/

> Note: [.browserslistrc](#browserslist) is used by postcss and is also needed to be overwritten. You can override that in that same directory or you may also configure postcss-preset-env to use default `.browserslistrc` path via environement variable to: `./node_modules/@greenwood/cli/src/config/.browserslistrc`. See [postcss-preset-env docs](https://www.npmjs.com/package/postcss-preset-env#browsers) for further information. [Ejecting configuration](#eject-configuration) is one way in which you can easily override both with no extra configuraiton.

### Webpack
The webpack config for production(`webpack.config.prod.js`) and development(`webpack.config.develop.js`) can be overridden by providing your own custom configuration within your project's directory. You can eject the default core configurations into your project using greenwood cli [eject](#eject-configurations) command and then edit them after, which is the simplest and recommended method for modifying webpack config. If you wish to revert back to the default provided configuration, simply delete these 2 files from your project's root directory.
A number of core build configuration files can be overridden by creating each file within the root path of your project.
### Eject Configurations

From greenwood CLI you can eject [core configuration files(webpack, postcss, babel, browserslistrc)](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/cli/src/config) into your project's working directory which will make it easier to add your own customizations. To do so, add the following to your package.json `scripts` object:
Expand Down
Loading

0 comments on commit bb21966

Please sign in to comment.