Skip to content

Commit

Permalink
Prevent name collision when parsing multiple files.
Browse files Browse the repository at this point in the history
  • Loading branch information
andyjansson committed Mar 1, 2017
1 parent b55fc91 commit d5b9291
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 217 deletions.
12 changes: 12 additions & 0 deletions packages/postcss-reduce-idents/src/__tests__/index.js
@@ -1,4 +1,5 @@
import test from 'ava';
import postcss from 'postcss';
import plugin from '..';
import encode from '../lib/encode';
import {usePostCSSPlugin, processCSSFactory} from '../../../../util/testHelpers';
Expand Down Expand Up @@ -249,6 +250,17 @@ test(
{encoder: val => `PREFIX${val}`}
);

test('should not generate same ident when plugin instance is reused', t => {
const instance = postcss(plugin);
return Promise.all([
instance.process('@keyframes whiteToBlack{0%{color:#fff}to{color:#000}}.one{animation-name:whiteToBlack}'),
instance.process('@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.two{animation-name:fadeOut}'),
]).then(([result1, result2]) => {
t.is(result1.css, '@keyframes a{0%{color:#fff}to{color:#000}}.one{animation-name:a}');
t.is(result2.css, '@keyframes b{0%{opacity:1}to{opacity:0}}.two{animation-name:b}');
});
});

test('encoder', t => {
let iterations = new Array(1984);
let arr = Array.apply([], iterations).map((a, b) => b);
Expand Down
8 changes: 4 additions & 4 deletions packages/postcss-reduce-idents/src/index.js
Expand Up @@ -14,10 +14,10 @@ export default postcss.plugin('postcss-reduce-idents', ({
encoder = encode,
} = {}) => {
const reducers = [];
counter && reducers.push(counterReducer);
counterStyle && reducers.push(counterStyleReducer);
keyframes && reducers.push(keyframesReducer);
gridTemplate && reducers.push(gridTemplateReducer);
counter && reducers.push(counterReducer());
counterStyle && reducers.push(counterStyleReducer());
keyframes && reducers.push(keyframesReducer());
gridTemplate && reducers.push(gridTemplateReducer());

return css => {
css.walk(node => {
Expand Down
88 changes: 45 additions & 43 deletions packages/postcss-reduce-idents/src/lib/counter-style.js
Expand Up @@ -13,53 +13,55 @@ const RESERVED_KEYWORDS = [
"trad-chinese-formal", "trad-chinese-informal", "upper-armenian", "disclosure-open", "disclosure-close",
];

let cache = {};
let atRules = [];
let decls = [];

export default {
export default function () {
let cache = {};
let atRules = [];
let decls = [];

collect (node, encoder) {
const {name, prop, type} = node;
return {
collect (node, encoder) {
const {name, prop, type} = node;

if (
type === 'atrule' &&
/counter-style/.test(name) &&
RESERVED_KEYWORDS.indexOf(node.params) === -1
) {
addToCache(node.params, encoder, cache);
atRules.push(node);
}

if (type === 'decl' && /(list-style|system)/.test(prop)) {
decls.push(node);
}
},
if (
type === 'atrule' &&
/counter-style/.test(name) &&
RESERVED_KEYWORDS.indexOf(node.params) === -1
) {
addToCache(node.params, encoder, cache);
atRules.push(node);
}

transform () {
// Iterate each property and change their names
decls.forEach(decl => {
decl.value = valueParser(decl.value).walk(node => {
if (node.type === 'word' && node.value in cache) {
cache[node.value].count++;
node.value = cache[node.value].ident;
} else if (node.type === 'space') {
node.value = ' ';
}
}).toString();
});
// Iterate each at rule and change their name if references to them have been found
atRules.forEach(rule => {
const cached = cache[rule.params];
if (cached && cached.count > 0) {
rule.params = cached.ident;
if (type === 'decl' && /(list-style|system)/.test(prop)) {
decls.push(node);
}
});
},

// reset cache after transform
cache = {};
atRules = [];
decls = [];
},
transform () {
// Iterate each property and change their names
decls.forEach(decl => {
decl.value = valueParser(decl.value).walk(node => {
if (node.type === 'word' && node.value in cache) {
cache[node.value].count++;
node.value = cache[node.value].ident;
} else if (node.type === 'space') {
node.value = ' ';
} else if (node.type === 'div') {
node.before = node.after = '';
}
}).toString();
});
// Iterate each at rule and change their name if references to them have been found
atRules.forEach(rule => {
const cached = cache[rule.params];
if (cached && cached.count > 0) {
rule.params = cached.ident;
}
});

};
// reset cache after transform
atRules = [];
decls = [];
},
};
}
133 changes: 66 additions & 67 deletions packages/postcss-reduce-idents/src/lib/counter.js
Expand Up @@ -6,77 +6,76 @@ const RESERVED_KEYWORDS = [
"unset", "initial", "inherit", "none",
];

let cache = {};
let declOneCache = [];
let declTwoCache = [];
export default function () {
let cache = {};
let declOneCache = [];
let declTwoCache = [];

export default {
return {
collect (node, encoder) {
const {prop, type} = node;

collect (node, encoder) {
const {prop, type} = node;
if (type !== 'decl') {
return;
}

if (type !== 'decl') {
return;
}
if (/counter-(reset|increment)/.test(prop)) {
node.value = valueParser(node.value).walk(child => {
if (
child.type === 'word' &&
!isNum(child) &&
RESERVED_KEYWORDS.indexOf(child.value) === -1
) {
addToCache(child.value, encoder, cache);
child.value = cache[child.value].ident;
}

if (/counter-(reset|increment)/.test(prop)) {
node.value = valueParser(node.value).walk(child => {
if (
child.type === 'word' &&
!isNum(child) &&
RESERVED_KEYWORDS.indexOf(child.value) === -1
) {
addToCache(child.value, encoder, cache);
child.value = cache[child.value].ident;
}
if (child.type === 'space') {
child.value = ' ';
}
});
declOneCache.push(node);
} else if (/content/.test(prop)) {
declTwoCache.push(node);
}
},

if (child.type === 'space') {
child.value = ' ';
}
transform () {
declTwoCache.forEach(decl => {
decl.value = valueParser(decl.value).walk(node => {
const {type, value} = node;
if (type === 'function' && (value === 'counter' || value === 'counters')) {
walk(node.nodes, child => {
if (child.type === 'word' && child.value in cache) {
cache[child.value].count++;
child.value = cache[child.value].ident;
} else if (child.type === 'div') {
child.before = child.after = '';
}
});
}
if (type === 'space') {
node.value = ' ';
}
return false;
}).toString();
});
declOneCache.forEach(decl => {
decl.value = decl.value.walk(node => {
if (node.type === 'word' && !isNum(node)) {
Object.keys(cache).forEach(key => {
const cached = cache[key];
if (cached.ident === node.value && !cached.count) {
node.value = key;
}
});
}
}).toString();
});
declOneCache.push(node);
} else if (/content/.test(prop)) {
declTwoCache.push(node);
}
},

transform () {
declTwoCache.forEach(decl => {
decl.value = valueParser(decl.value).walk(node => {
const {type, value} = node;
if (type === 'function' && (value === 'counter' || value === 'counters')) {
walk(node.nodes, child => {
if (child.type === 'word' && child.value in cache) {
cache[child.value].count++;
child.value = cache[child.value].ident;
} else if (child.type === 'div') {
child.before = child.after = '';
}
});
}
if (type === 'space') {
node.value = ' ';
}
return false;
}).toString();
});
declOneCache.forEach(decl => {
decl.value = decl.value.walk(node => {
if (node.type === 'word' && !isNum(node)) {
Object.keys(cache).forEach(key => {
const cached = cache[key];
if (cached.ident === node.value && !cached.count) {
node.value = key;
}
});
}
}).toString();
});

// reset cache after transform
cache = {};
declOneCache = [];
declTwoCache = [];
},

};
// reset cache after transform
declOneCache = [];
declTwoCache = [];
},
};
}
105 changes: 52 additions & 53 deletions packages/postcss-reduce-idents/src/lib/grid-template.js
Expand Up @@ -6,62 +6,61 @@ const RESERVED_KEYWORDS = [
"auto", "span", "inherit", "initial", "unset",
];

let cache = {};
let declCache = [];
export default function () {
let cache = {};
let declCache = [];

export default {
return {
collect (node, encoder) {
if (node.type !== 'decl') {
return;
}

collect (node, encoder) {
if (node.type !== 'decl') {
return;
}

if (/(grid-template|grid-template-areas)/.test(node.prop)) {
valueParser(node.value).walk(child => {
if (child.type === 'string') {
child.value.split(/\s+/).forEach(word => {
if (/\.+/.test(word)) { // reduce empty zones to a single `.`
node.value = node.value.replace(word, ".");
} else {
addToCache(word, encoder, cache);
}
});
}
});
declCache.push(node);
} else if (node.prop === 'grid-area') {
valueParser(node.value).walk(child => {
if (child.type === 'word' && RESERVED_KEYWORDS.indexOf(child.value) === -1) {
addToCache(child.value, encoder, cache);
}
});
declCache.push(node);
}
},
if (/(grid-template|grid-template-areas)/.test(node.prop)) {
valueParser(node.value).walk(child => {
if (child.type === 'string') {
child.value.split(/\s+/).forEach(word => {
if (/\.+/.test(word)) { // reduce empty zones to a single `.`
node.value = node.value.replace(word, ".");
} else if (word && RESERVED_KEYWORDS.indexOf(word) === -1) {
addToCache(word, encoder, cache);
}
});
}
});
declCache.push(node);
} else if (node.prop === 'grid-area') {
valueParser(node.value).walk(child => {
if (child.type === 'word' && RESERVED_KEYWORDS.indexOf(child.value) === -1) {
addToCache(child.value, encoder, cache);
}
});
declCache.push(node);
}
},

transform () {
declCache.forEach(decl => {
decl.value = valueParser(decl.value).walk(node => {
if (/(grid-template|grid-template-areas)/.test(decl.prop)) {
node.value.split(/\s+/).forEach(word => {
if (word in cache) {
node.value = node.value.replace(word, cache[word].ident);
transform () {
declCache.forEach(decl => {
decl.value = valueParser(decl.value).walk(node => {
if (/(grid-template|grid-template-areas)/.test(decl.prop)) {
node.value.split(/\s+/).forEach(word => {
if (word in cache) {
node.value = node.value.replace(word, cache[word].ident);
}
});
node.value = node.value.replace(/\s+/g, " "); // merge white-spaces
}
if (decl.prop === 'grid-area' && !isNum(node)) {
if (node.value in cache) {
node.value = cache[node.value].ident;
}
});
node.value = node.value.replace(/\s+/g, " "); // merge white-spaces
}
if (decl.prop === 'grid-area' && !isNum(node)) {
if (node.value in cache) {
node.value = cache[node.value].ident;
}
}
return false;
}).toString();
});

// reset cache after transform
cache = {};
declCache = [];
},
return false;
}).toString();
});

};
// reset cache after transform
declCache = [];
},
};
}

0 comments on commit d5b9291

Please sign in to comment.