Skip to content

Commit

Permalink
Improve nested rules management system
Browse files Browse the repository at this point in the history
  • Loading branch information
dimitrinicolas committed Aug 11, 2018
1 parent a3162d3 commit 18d2a1f
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 82 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
This project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 1.2.1 - 2018-08-11
### Changed
- Simpler nested rules management system.

## 1.2.0 - 2018-08-11
### Added
- Now packing together same media queries and same selectors, respecting css
Expand Down
95 changes: 24 additions & 71 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,29 +105,6 @@ const parse = (nodes, opts) => {
};
};

/**
* Return the css rule parent of depth 1
* @param {rule} rule
*/
const deepParent = rule => {
if (rule.parent.type === 'rule') {
return deepParent(rule.parent);
}
return rule;
};

/**
* Return nested selector
* @param {rule} rule
* @param {string} [suffix='']
*/
const deepParentSelector = (rule, suffix = '') => {
if (rule.parent.type === 'rule') {
return deepParentSelector(rule.parent, `${rule.parent.selector} ${suffix}`);
}
return suffix;
};

/**
* Query class
* @param {string} selector
Expand Down Expand Up @@ -166,56 +143,34 @@ class Query {
/**
* RulePack class
* @param {string} parent
* @param {string} selector
*/
class RulePack {
constructor(parent) {
constructor(parent, selector) {
this.parent = parent;
this.selector = selector;
this.queries = [];
}

addQuery({ selector, prop, content }) {
addQuery({ prop, content }) {
content.queries.forEach(({ media, value }) => {
let foundMedia = false;
this.queries.forEach(item => {
if (item.media === media && !foundMedia) {
foundMedia = true;

let foundSelector = false;
item.selectors.forEach(selectorPack => {
if (selectorPack.selector === selector && !foundSelector) {
foundSelector = true;

selectorPack.queries.push({
prop,
value
});
}
item.queries.push({
prop,
value
});
if (!foundSelector) {
item.selectors.push({
selector,
queries: [
{
prop,
value
}
]
});
}
}
});
if (!foundMedia) {
this.queries.push({
media,
selectors: [
queries: [
{
selector,
queries: [
{
prop,
value
}
]
prop,
value
}
]
});
Expand All @@ -238,16 +193,16 @@ module.exports = postcss.plugin('postcss-inline-media', (opts = {}) => {
shorthandUnit: typeof opts.shorthandUnit === 'string'
? opts.shorthandUnit : 'px'
});
const parent = deepParent(rule);

const query = new Query(deepParentSelector(rule), rule.prop, content);
const query = new Query(rule.parent.selector, rule.prop, content);
if (
mediaQueries.length
&& mediaQueries[mediaQueries.length - 1].parent === parent
&& mediaQueries[mediaQueries.length - 1].parent === rule.parent
&& mediaQueries[mediaQueries.length - 1].selector === query.selector
) {
mediaQueries[mediaQueries.length - 1].addQuery(query);
} else {
const pack = new RulePack(parent);
const pack = new RulePack(rule.parent, query.selector);
pack.addQuery(query);
mediaQueries.push(pack);
}
Expand All @@ -264,26 +219,24 @@ module.exports = postcss.plugin('postcss-inline-media', (opts = {}) => {
});

mediaQueries.forEach(mq => {
const root = mq.parent.root();
const root = mq.parent.parent;

mq.queries.forEach(({ media, selectors }) => {
mq.queries.forEach(({ media, queries }) => {
const atRule = postcss.atRule({
name: 'media',
params: media
});

selectors.forEach(({ selector, queries }) => {
const mediaRule = postcss.rule({
selector
});
queries.forEach(({ prop, value }) => {
mediaRule.append({
prop,
value
});
const mediaRule = postcss.rule({
selector: mq.selector
});
queries.forEach(({ prop, value }) => {
mediaRule.append({
prop,
value
});
atRule.append(mediaRule);
});
atRule.append(mediaRule);

root.append(atRule);
});
Expand Down
47 changes: 36 additions & 11 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,21 +179,46 @@ test('postcss-media-minmax many', async t => {
});
});

test('test', async t => {
test('nested rules', async t => {
const input = 'div { margin: 20px @900 10px @600 5px; padding: 20px @900 10px; header { span { color: black @900 red; } } } span { color: black @900 red; }';
const output = [
'div { margin: 20px; padding: 20px; header { span { color: black; } } }',
'span { color: black; }',
'@media (max-width: 900px) {',
'div {',
'margin: 20px; padding: 20px; header {',
'span { color: black; } @media (max-width: 900px) { span { color: red; } }',
'} } span { color: black; } @media (max-width: 900px) {',
'div { margin: 10px; padding: 10px; }',
'div header span { color: red; }',
'}',
'@media (max-width: 600px) {',
'div { margin: 5px; }',
'}',
'} @media (max-width: 600px) { div { margin: 5px; } }',
'@media (max-width: 900px) { span { color: red; } }'
].join(' ');
testPostcss(input, output, t);
});

test('nested pseudo element', async t => {
const input = 'div { margin: 20px @900 10px; padding: @600 10px; &::before { color: black @900 red; } }';
const output = [
'div {',
'margin: 20px; &::before { color: black; }',
'@media (max-width: 900px) {',
'&::before { color: red; }',
'} }',
'@media (max-width: 900px) {',
'div { margin: 10px; }',
'} @media (max-width: 600px) { div { padding: 10px; } }'
].join(' ');
testPostcss(input, output, t);
});

test('nested unknown rule type', async t => {
const input = 'div { margin: 20px @900 10px; padding: @600 10px; -something { color: black @900 red; } }';
const output = [
'div {',
'margin: 20px; -something { color: black; }',
'@media (max-width: 900px) {',
'-something { color: red; }',
'} }',
'@media (max-width: 900px) {',
'span { color: red; }',
'}'
'div { margin: 10px; }',
'} @media (max-width: 600px) { div { padding: 10px; } }'
].join(' ');
testPostcss(input, output, t);
});

0 comments on commit 18d2a1f

Please sign in to comment.