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

Fix to issue with async output and missing output directory #27

Open
wants to merge 8 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
17 changes: 15 additions & 2 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
{
"presets": ["es2015"],
"plugins": ["transform-flow-strip-types", "transform-object-rest-spread"]
"presets": [
["env", {
"targets": {
"node": "6"
}
}]
],
"plugins": [
["transform-runtime", {
"polyfill": false,
"regenerator": true
}],
"transform-flow-strip-types",
"transform-object-rest-spread"
]
}
2 changes: 2 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ignore]
.*/node_modules/.*/node_modules/.*
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,11 @@ Will output:

The plugin takes a single object as its only parameter. The following properties are valid:

| Arg | Type | Description | Default |
| ------------ | --------- | ------------------------------------------- | ------------------------- |
| `outputPath` | `string` | Path to which critical CSS should be output | Current working directory |
| `outputDest` | `string` | Default critical CSS file name | `"critical.css"` |
| `preserve` | `boolean` | Whether or not to remove selectors from primary CSS document once they've been marked as critical. This should prevent duplication of selectors across critical and non-critical CSS. | `true` |
| `minify` | `boolean` | Minify output CSS? | `true` |
| Arg | Type | Description | Default |
| ----------------- | --------- | ------------------------------------------- | ------------------------- |
| `outputPath` | `string` | Path to which critical CSS should be output | Current working directory |
| `outputDest` | `string` | Default critical CSS file name | `"critical.css"` |
| `preserve` | `boolean` | Whether or not to remove selectors from primary CSS document once they've been marked as critical. This should prevent duplication of selectors across critical and non-critical CSS. | `true` |
| `minify` | `boolean` | Minify output CSS? | `true` |
| `ignoreSelectors` | `array` | Array of selectors to globally exclude from critical CSS output | `[]` |
| `fsWriteRate` | `number` | Minimum amount of time between file writes, in millisenconds. This is intended to prevent overlapping file writes for codebases with numerous calls to `@critical` | `250` |
1 change: 0 additions & 1 deletion critical.css

This file was deleted.

1 change: 0 additions & 1 deletion default.critical.expected.css

This file was deleted.

9 changes: 0 additions & 9 deletions default.css

This file was deleted.

7 changes: 0 additions & 7 deletions default.non-critical.actual.css

This file was deleted.

7 changes: 0 additions & 7 deletions default.non-critical.expected.css

This file was deleted.

16 changes: 9 additions & 7 deletions lib/atRule.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

exports.getCriticalFromAtRule = getCriticalFromAtRule;

Expand All @@ -20,20 +22,20 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
* @param {Object} args Function args. See flow type alias.
*/
function getCriticalFromAtRule(args) {
var result = {};
var options = _extends({
const result = {};
const options = (0, _extends3.default)({
defaultDest: 'critical.css',
css: _postcss2.default.root()
}, args);

options.css.walkAtRules('critical', function (atRule) {
var name = atRule.params ? atRule.params : options.defaultDest;
options.css.walkAtRules('critical', atRule => {
const name = atRule.params ? atRule.params : options.defaultDest;
// If rule has no nodes, all the nodes of the parent will be critical.
var rule = atRule;
let rule = atRule;
if (!atRule.nodes) {
rule = atRule.root();
}
rule.clone().each(function (node) {
rule.clone().each(node => {
if (node.name !== 'critical') {
result[name] = result[name] ? result[name].append(node) : _postcss2.default.root().append(node);
}
Expand Down
18 changes: 9 additions & 9 deletions lib/getChildRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
* @return {array} Array of child rules.
*/
function getChildRules(css, parent) {
var result = [];
var selectorRegExp = new RegExp(parent.selector);
const result = [];
const selectorRegExp = new RegExp(parent.selector);

// Walk all rules to mach child selectors
css.walkRules(selectorRegExp, function (rule) {
var childRule = (0, _matchChild.matchChild)(parent, rule);
css.walkRules(selectorRegExp, rule => {
const childRule = (0, _matchChild.matchChild)(parent, rule);
if (childRule) {
result.push(rule);
}
});

// Walk all at-rules to match nested child selectors
css.walkAtRules(function (atRule) {
atRule.walkRules(selectorRegExp, function (rule) {
var childRule = (0, _matchChild.matchChild)(parent, rule);
css.walkAtRules(atRule => {
atRule.walkRules(selectorRegExp, rule => {
const childRule = (0, _matchChild.matchChild)(parent, rule);
// Create new at-rule to append only necessary selector to critical
var criticalAtRule = _postcss2.default.atRule({
const criticalAtRule = _postcss2.default.atRule({
name: atRule.name,
params: atRule.params
});
Expand All @@ -46,7 +46,7 @@ function getChildRules(css, parent) {
* aren't identical.
*/
if ((rule.selector === parent.selector || childRule) && _postcss2.default.parse(rule).toString() !== _postcss2.default.parse(parent).toString()) {
var clone = rule.clone();
const clone = rule.clone();
criticalAtRule.append(clone);
result.push(criticalAtRule);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/getCriticalDestination.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exports.getCriticalDestination = getCriticalDestination;
* @return {string} String corresponding to output destination.
*/
function getCriticalDestination(rule, dest) {
rule.walkDecls('critical-filename', function (decl) {
rule.walkDecls('critical-filename', decl => {
dest = decl.value.replace(/['"]*/g, '');
decl.remove();
});
Expand Down
40 changes: 19 additions & 21 deletions lib/getCriticalRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
* @param {string} test Declaration string. Default `critical-selector`
* @return {Object} clone Cloned, cleaned root node.
*/
function clean(root) {
var test = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'critical-selector';

var clone = root.clone();
function clean(root, test = 'critical-selector') {
const clone = root.clone();
if (clone.type === 'decl') {
clone.remove();
} else {
clone.walkDecls(test, function (decl) {
clone.walkDecls(test, decl => {
decl.remove();
});
}
Expand All @@ -45,12 +43,12 @@ function clean(root) {
* @return {Object} sortedRoot Root with nodes sorted by source order.
*/
function correctSourceOrder(root) {
var sortedRoot = _postcss2.default.root();
var clone = root.clone();
clone.walkRules(function (rule) {
var start = rule.source.start.line;
const sortedRoot = _postcss2.default.root();
const clone = root.clone();
clone.walkRules(rule => {
let start = rule.source.start.line;
if (rule.parent.type === 'atrule') {
var child = rule;
const child = rule;
rule = _postcss2.default.atRule({
name: rule.parent.name,
params: rule.parent.params
Expand Down Expand Up @@ -91,11 +89,11 @@ function establishContainer(node) {
* @return {Object} clonedRoot Root object.
*/
function updateCritical(root, update) {
var clonedRoot = root.clone();
const clonedRoot = root.clone();
if (update.type === 'rule') {
clonedRoot.append(clean(update.clone()));
} else {
update.clone().each(function (rule) {
update.clone().each(rule => {
clonedRoot.append(clean(rule.root()));
});
}
Expand All @@ -111,21 +109,21 @@ function updateCritical(root, update) {
* @return {object} Object containing critical rules, organized by output destination
*/
function getCriticalRules(css, defaultDest) {
var critical = (0, _atRule.getCriticalFromAtRule)({ css: css, defaultDest: defaultDest });
css.walkDecls('critical-selector', function (decl) {
var parent = decl.parent,
value = decl.value;

var dest = (0, _getCriticalDestination.getCriticalDestination)(parent, defaultDest);
var container = establishContainer(parent);
var childRules = value === 'scope' ? (0, _getChildRules.getChildRules)(css, parent) : [];
const critical = (0, _atRule.getCriticalFromAtRule)({ css, defaultDest });
css.walkDecls('critical-selector', decl => {
const parent = decl.parent,
value = decl.value;

const dest = (0, _getCriticalDestination.getCriticalDestination)(parent, defaultDest);
const container = establishContainer(parent);
const childRules = value === 'scope' ? (0, _getChildRules.getChildRules)(css, parent) : [];
// Sanity check, make sure we've got a root node
critical[dest] = critical[dest] || _postcss2.default.root();

switch (value) {
case 'scope':
// Add all child rules
var criticalRoot = childRules.reduce(function (acc, rule) {
const criticalRoot = childRules.reduce((acc, rule) => {
return acc.append(rule.clone());
}, critical[dest].append(container));

Expand Down
Loading