Skip to content

Commit

Permalink
Split sort logic from configuration loading process
Browse files Browse the repository at this point in the history
  • Loading branch information
WezomDev committed May 26, 2021
1 parent ed56f3a commit 4744eac
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 250 deletions.
245 changes: 245 additions & 0 deletions lib/create-sort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
// ----------------------------------------
// Private
// ----------------------------------------

const minMaxWidth = /(!?\(\s*min(-device-)?-width)(.|\n)+\(\s*max(-device)?-width/i;
const minWidth = /\(\s*min(-device)?-width/i;
const maxMinWidth = /(!?\(\s*max(-device)?-width)(.|\n)+\(\s*min(-device)?-width/i;
const maxWidth = /\(\s*max(-device)?-width/i;

const isMinWidth = _testQuery(minMaxWidth, maxMinWidth, minWidth);
const isMaxWidth = _testQuery(maxMinWidth, minMaxWidth, maxWidth);

const minMaxHeight = /(!?\(\s*min(-device)?-height)(.|\n)+\(\s*max(-device)?-height/i;
const minHeight = /\(\s*min(-device)?-height/i;
const maxMinHeight = /(!?\(\s*max(-device)?-height)(.|\n)+\(\s*min(-device)?-height/i;
const maxHeight = /\(\s*max(-device)?-height/i;

const isMinHeight = _testQuery(minMaxHeight, maxMinHeight, minHeight);
const isMaxHeight = _testQuery(maxMinHeight, minMaxHeight, maxHeight);

const isPrint = /print/i;
const isPrintOnly = /^print$/i;

const maxValue = Number.MAX_VALUE;

/**
* Obtain the length of the media request in pixels.
* Copy from original source `function inspectLength (length)`
* {@link https://github.com/hail2u/node-css-mqpacker/blob/master/index.js#L58}
* @private
* @param {string} length
* @return {number}
*/
function _getQueryLength(length) {
length = /(-?\d*\.?\d+)(ch|em|ex|px|rem)/.exec(length);

if (length === null) {
return maxValue;
}

let number = length[1];
const unit = length[2];

switch (unit) {
case 'ch':
number = parseFloat(number) * 8.8984375;
break;

case 'em':
case 'rem':
number = parseFloat(number) * 16;
break;

case 'ex':
number = parseFloat(number) * 8.296875;
break;

case 'px':
number = parseFloat(number);
break;
}

return +number;
}

/**
* Wrapper for creating test functions
* @private
* @param {RegExp} doubleTestTrue
* @param {RegExp} doubleTestFalse
* @param {RegExp} singleTest
* @return {Function}
*/
function _testQuery(doubleTestTrue, doubleTestFalse, singleTest) {
/**
* @param {string} query
* @return {boolean}
*/
return function (query) {
if (doubleTestTrue.test(query)) {
return true;
} else if (doubleTestFalse.test(query)) {
return false;
}
return singleTest.test(query);
};
}

/**
* @private
* @param {string} a
* @param {string} b
* @return {number|null}
*/
function _testIsPrint(a, b) {
const isPrintA = isPrint.test(a);
const isPrintOnlyA = isPrintOnly.test(a);

const isPrintB = isPrint.test(b);
const isPrintOnlyB = isPrintOnly.test(b);

if (isPrintA && isPrintB) {
if (!isPrintOnlyA && isPrintOnlyB) {
return 1;
}
if (isPrintOnlyA && !isPrintOnlyB) {
return -1;
}
return a.localeCompare(b);
}
if (isPrintA) {
return 1;
}
if (isPrintB) {
return -1;
}

return null;
}

// ----------------------------------------
// Public
// ----------------------------------------

/**
* @param {Object} [configuration]
* @param {boolean} [configuration.unitlessMqAlwaysFirst]
* @returns {(function(string, string): number)|*}
*/
module.exports = function createSort(configuration) {
const config = configuration || {};

// eslint-disable-next-line no-unused-vars
const UNITLESS_MQ_ALWAYS_FIRST = config.unitlessMqAlwaysFirst;

/**
* Sorting an array with media queries
* according to the mobile-first methodology.
* @param {string} a
* @param {string} b
* @return {number} 1 / 0 / -1
*/
function sortCSSmq(a, b) {
const testIsPrint = _testIsPrint(a, b);
if (testIsPrint !== null) {
return testIsPrint;
}

const minA = isMinWidth(a) || isMinHeight(a);
const maxA = isMaxWidth(a) || isMaxHeight(a);

const minB = isMinWidth(b) || isMinHeight(b);
const maxB = isMaxWidth(b) || isMaxHeight(b);

if (minA && maxB) {
return -1;
}
if (maxA && minB) {
return 1;
}

const lengthA = _getQueryLength(a);
const lengthB = _getQueryLength(b);

if (lengthA === maxValue && lengthB === maxValue) {
return a.localeCompare(b);
} else if (lengthA === maxValue) {
return 1;
} else if (lengthB === maxValue) {
return -1;
}

if (lengthA > lengthB) {
if (maxA) {
return -1;
}
return 1;
}

if (lengthA < lengthB) {
if (maxA) {
return 1;
}
return -1;
}

return a.localeCompare(b);
}

/**
* Sorting an array with media queries
* according to the desktop-first methodology.
* @param {string} a
* @param {string} b
* @return {number} 1 / 0 / -1
*/
sortCSSmq.desktopFirst = function (a, b) {
const testIsPrint = _testIsPrint(a, b);
if (testIsPrint !== null) {
return testIsPrint;
}

const minA = isMinWidth(a) || isMinHeight(a);
const maxA = isMaxWidth(a) || isMaxHeight(a);

const minB = isMinWidth(b) || isMinHeight(b);
const maxB = isMaxWidth(b) || isMaxHeight(b);

if (minA && maxB) {
return 1;
}
if (maxA && minB) {
return -1;
}

const lengthA = _getQueryLength(a);
const lengthB = _getQueryLength(b);

if (lengthA === maxValue && lengthB === maxValue) {
return a.localeCompare(b);
} else if (lengthA === maxValue) {
return 1;
} else if (lengthB === maxValue) {
return -1;
}

if (lengthA > lengthB) {
if (maxA) {
return -1;
}
return 1;
}

if (lengthA < lengthB) {
if (maxA) {
return 1;
}
return -1;
}

return -a.localeCompare(b);
};

return sortCSSmq;
};
Loading

0 comments on commit 4744eac

Please sign in to comment.