diff --git a/src/generate.js b/src/generate.js index 2b23ab0..fe51260 100644 --- a/src/generate.js +++ b/src/generate.js @@ -177,7 +177,7 @@ export const generateCSS = ( // If none of the handlers handled it, add it to the list of plain // style declarations. if (!foundHandler) { - plainDeclarations.set(key, val); + plainDeclarations.set(key, val, true); } }); @@ -199,9 +199,9 @@ const runStringHandlers = ( declarations /* : OrderedElements */, stringHandlers /* : StringHandlers */, selectorHandlers /* : SelectorHandler[] */ -) /* : OrderedElements */ => { +) /* : void */ => { if (!stringHandlers) { - return declarations; + return; } const stringHandlerKeys = Object.keys(stringHandlers); @@ -219,12 +219,15 @@ const runStringHandlers = ( // handlers are very specialized and do complex things. declarations.set( key, - stringHandlers[key](declarations.get(key), selectorHandlers) + stringHandlers[key](declarations.get(key), selectorHandlers), + + // Preserve order here, since we are really replacing an + // unprocessed style with a processed style, not overriding an + // earlier style + false ); } } - - return declarations; }; diff --git a/src/ordered-elements.js b/src/ordered-elements.js index 2d30f8c..456867d 100644 --- a/src/ordered-elements.js +++ b/src/ordered-elements.js @@ -19,9 +19,13 @@ export default class OrderedElements { } } - set(key /* : string */, value /* : any */) { + set(key /* : string */, value /* : any */, shouldReorder /* : ?boolean */) { if (!this.elements.hasOwnProperty(key)) { this.keyOrder.push(key); + } else if (shouldReorder) { + const index = this.keyOrder.indexOf(key); + this.keyOrder.splice(index, 1); + this.keyOrder.push(key); } if (value == null) { @@ -36,7 +40,7 @@ export default class OrderedElements { ? this.elements[key] : new OrderedElements(); value.forEach((value, key) => { - nested.set(key, value); + nested.set(key, value, shouldReorder); }); this.elements[key] = nested; return; @@ -50,7 +54,7 @@ export default class OrderedElements { : new OrderedElements(); const keys = Object.keys(value); for (let i = 0; i < keys.length; i += 1) { - nested.set(keys[i], value[keys[i]]); + nested.set(keys[i], value[keys[i]], shouldReorder); } this.elements[key] = nested; return; @@ -70,12 +74,12 @@ export default class OrderedElements { addStyleType(styleType /* : any */) /* : void */ { if ((MAP_EXISTS && styleType instanceof Map) || styleType instanceof OrderedElements) { styleType.forEach((value, key) => { - this.set(key, value); + this.set(key, value, true); }); } else { const keys = Object.keys(styleType); for (let i = 0; i < keys.length; i++) { - this.set(keys[i], styleType[keys[i]]); + this.set(keys[i], styleType[keys[i]], true); } } } diff --git a/tests/generate_test.js b/tests/generate_test.js index 501de28..309d70c 100644 --- a/tests/generate_test.js +++ b/tests/generate_test.js @@ -258,6 +258,34 @@ ${formatStyles(actual)} }`, defaultSelectorHandlers); }); + it('orders overrides in the expected way', () => { + assertCSS('.foo', [ + { + "@media (min-width: 400px)": { + padding: 10, + } + }, + { + "@media (min-width: 200px)": { + padding: 20, + }, + "@media (min-width: 400px)": { + padding: 30, + } + } + ], ` + @media (min-width: 200px){ + .foo{ + padding:20px !important; + } + } + @media (min-width: 400px){ + .foo{ + padding:30px !important; + } + }`, defaultSelectorHandlers); + }); + it('supports custom string handlers', () => { assertCSS('.foo', [{ fontFamily: ["Helvetica", "sans-serif"] diff --git a/tests/ordered-elements_test.js b/tests/ordered-elements_test.js index 3a49e9c..352b91a 100644 --- a/tests/ordered-elements_test.js +++ b/tests/ordered-elements_test.js @@ -53,6 +53,38 @@ describe("OrderedElements", () => { }, elems); }); + it('preserves original order when overriding', () => { + const elems = new OrderedElements(); + + elems.set("a", 1); + elems.set("b", 1); + elems.set("a", 2); + + assert.deepEqual({ + elements: { + a: 2, + b: 1, + }, + keyOrder: ["a", "b"], + }, elems); + }); + + it('can reorder when overriding', () => { + const elems = new OrderedElements(); + + elems.set("a", 1); + elems.set("b", 1); + elems.set("a", 2, true); + + assert.deepEqual({ + elements: { + b: 1, + a: 2, + }, + keyOrder: ["b", "a"], + }, elems); + }); + it("iterates over the elements in the correct order", () => { const elems = new OrderedElements();