Skip to content

Commit

Permalink
Sort prefixed values before unprefixed values with the same key
Browse files Browse the repository at this point in the history
Summary: In #200 the way we started sorting prefixed and unprefixed values
differently. This builds on that by making sure that when style values are
prefixed, they come before the unprefixed values with the same key.

E.g.

```css
display: -webkit-flex; // prefixed value comes before
display: flex;         // unprefixed value
```

@lencioni
  • Loading branch information
xymostech committed Mar 8, 2017
1 parent fb98507 commit d8a629b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 27 deletions.
69 changes: 43 additions & 26 deletions src/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,25 @@ export const generateCSSRuleset = (
const handledDeclarations /* : OrderedElements */ = runStringHandlers(
declarations, stringHandlers, selectorHandlers);

const originalElements = {...handledDeclarations.elements};

// NOTE(emily): This mutates handledDeclarations.elements.
const prefixedDeclarations = prefixAll(handledDeclarations.elements);

const prefixedRules = flatten(
objectToPairs(prefixedDeclarations).map(([key, value]) => {
if (Array.isArray(value)) {
// inline-style-prefixer returns an array when there should be
// multiple rules for the same key. Here we flatten to multiple
// pairs with the same key.
return value.map(v => [key, v]);
}
return [[key, value]];
})
);

// Calculate the order that we want to each element in `prefixedRules` to
// be in, based on its index in the original key ordering. We have to do
// this before the prefixing, because prefixAll mutates
// handledDeclarations.elements.
// be in, based on its index in the original key ordering.
const sortOrder = {};
for (let i = 0; i < handledDeclarations.keyOrder.length; i++) {
const key = handledDeclarations.keyOrder[i];
Expand All @@ -275,36 +290,38 @@ export const generateCSSRuleset = (
`ms${capitalizedKey}`,
];
for (let j = 0; j < prefixedKeys.length; ++j) {
if (!handledDeclarations.elements.hasOwnProperty(prefixedKeys[j])) {
if (!originalElements.hasOwnProperty(prefixedKeys[j])) {
sortOrder[prefixedKeys[j]] = i - 0.5;
originalElements[prefixedKeys[j]] = originalElements[key];
}
}
}

// NOTE(emily): This mutates handledDeclarations.elements.
const prefixedDeclarations = prefixAll(handledDeclarations.elements);

const prefixedRules = flatten(
objectToPairs(prefixedDeclarations).map(([key, value]) => {
if (Array.isArray(value)) {
// inline-style-prefixer returns an array when there should be
// multiple rules for the same key. Here we flatten to multiple
// pairs with the same key.
return value.map(v => [key, v]);
// Calculate the sort order of a given property.
function sortOrderForProperty([key, value]) {
if (sortOrder.hasOwnProperty(key)) {
if (originalElements.hasOwnProperty(key) &&
originalElements[key] !== value) {
// The value is prefixed. Sort this just before the key with
// the unprefixed value.
return sortOrder[key] - 0.25;
} else {
// Either the key and value are unprefixed here, or this is a
// prefixed key. Either way, this is handled by the sortOrder
// calculation above.
return sortOrder[key];
}
return [[key, value]];
})
);
} else {
// If the property isn't in the sort order, it wasn't in the
// original set of unprefixed keys, so it must be a prefixed key.
// Sort at order -1 to put it at the top of the set of styles.
return -1;
}
}

// Sort the prefixed rules according to the order that the keys were
// in originally before we prefixed them. New, prefixed versions
// of the rules aren't in the original list, so we set their order to -1 so
// they sort to the top.
prefixedRules.sort((a, b) => {
const aOrder = sortOrder.hasOwnProperty(a[0]) ? sortOrder[a[0]] : -1;
const bOrder = sortOrder.hasOwnProperty(b[0]) ? sortOrder[b[0]] : -1;
return aOrder - bOrder;
});
// Actually sort the rules according to the sort order.
prefixedRules.sort(
(a, b) => sortOrderForProperty(a) - sortOrderForProperty(b));

const transformValue = (useImportant === false)
? stringifyValue
Expand Down
2 changes: 1 addition & 1 deletion tests/generate_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,11 @@ ${formatStyles(actual)}
'-ms-flex-pack:center !important;' +
'-webkit-box-align:center !important;' +
'-ms-flex-align:center !important;' +
'display:flex !important;' +
'display:-webkit-box !important;' +
'display:-ms-flexbox !important;' +
'display:-webkit-flex !important;' +
'display:-moz-box !important;' +
'display:flex !important;' +
'-webkit-transition:all 0s !important;' +
'-moz-transition:all 0s !important;' +
'transition:all 0s !important;' +
Expand Down

0 comments on commit d8a629b

Please sign in to comment.